12. rust网络编程基础

一、前言

网络开发是各种语言都绕不开的话题,所以本章就来详细介绍一下rust语言网络开发的技巧。

如果你还不理解网络的基本工作原理,可以先参考文章:网络编程

二、TCP编程

首先依旧是TCP协议,相比于C++,在rust中进行网络编程就要简单的多了,因为其默认封装了大量的细节。

比如一个最简单的TCP回声服务器写法如下:

use std::{
    io::{Read, Write},
    net::TcpListener,
};

fn main() {
    let listener = TcpListener::bind("127.0.0.1:8888").unwrap();
    for cli in listener.incoming() {
        let Ok(mut cli) = cli else {
            println!("error:{:?}", cli.unwrap_err());
            continue;
        };

        std::thread::spawn(move || loop {
            let mut buf = [0; 1024]; //申请接收数据的缓冲区
            let ret = cli.read(&mut buf); //开始接受数据

            if let Err(e) = ret {
                println!("接收数据失败:{}", e);
                break;
            };

            println!(
                "接收到来自客户端的数据:{}",
                String::from_utf8(buf.to_vec()).unwrap() //使用from_utf8将字节数据转换为字符串进行输出。
            );
            let ret = cli.write_all(&buf); //将收到的数据重新发送给客户端

            if let Err(e) = ret {
                println!("发送数据失败:{}", e);
                break;
            }
        });
    }
}

由于rust已经为我们封装了大量的底层细节,所以这里就简单理一下这段代码的工作逻辑即可。

  1. 首先使用TcpListener上的bind方法绑定地址、端口,然后返回一个tcp服务器实例。
  2. 紧接着调用该实例上的incoming函数获取连接到该服务上的客户端实例迭代器,如果暂时没有客户端连接上来,那么程序会卡在这里。
  3. 然后来到循环内部,为每个连接上来的客户端都开启一个线程进入loop循环不断处理其数据。

read方法可以接收客户端发送来的字节,write_all则用于向客户端发送数据。

所以最后就是直接将客户端发送来的数据直接发送回去,实现一个“回声服务器”的效果。

然后是客户端代码,就更简单了:

use std::{
    io::{Read, Write},
    net::TcpStream,
};

fn main() {
    let mut cli = TcpStream::connect("127.0.0.1:8888").unwrap();
    loop {
        let mut buf = String::new();
        std::io::stdin().read_line(&mut buf).unwrap(); //接受命令行输入的文本内容,每次读取一行
        let buf: &[u8] = &buf.into_bytes(); //转换为字节数据
        let ret = cli.write_all(buf); //发送字节数据
        if let Err(e) = ret {
            println!("发送数据失败:{}", e);
            break;
        }
        let mut buf = [0; 1024];
        let ret = cli.read(&mut buf); //接收服务器返回的数据

        if let Err(e) = ret {
            println!("接收数据失败:{}", e);
            break;
        }

        println!(
            "接收到来自服务器的数据:{}",
            String::from_utf8(buf.to_vec()).unwrap()
        );
    }
}

下面是简单的代码逻辑分析:

  1. 首先使用TcpStream内的connect函数连接服务器,得到一个可以与服务器收发数据的实例。
  2. 然后使用loop无限循环,每次循环都从控制台读取一行用户输入的内容发送给服务器
  3. 最后再从服务器接收数据,并将其转换为字符串打印出来。

然后将上面两份代码分别编译,或者你也可以直接建两个rust项目,分别同时运行。

作者:余识
全部文章:0
会员文章:0
总阅读量:0
c/c++pythonrustJavaScriptwindowslinux