用Rust实现TCP Echo客户端
本文主要讲解《Rustで始めるネットワークプログラミング》一书1.5节的内容——用Rust实现一个TCP Echo客户端。
TCP Echo客户端
虽然用telnet或nc也能够测试(上一节实现的)TCP Echo服务器,但我们还是用Rust创建一个TCP Echo客户端吧。它的主要功能包括:
- 将从标准输入读入的数据发送到TCP Echo服务器
- 将从TCP Echo服务器接收到的数据输出到标准输出
TCP Echo客户端的源代码如下所示。
#[macro_use]
extern crate log;
use std::env;
use std::io::{self, BufRead, BufReader, Write};
use std::net::TcpStream;
use std::str;
fn main() {
env::set_var("RUST_LOG", "debug");
env_logger::init();
let address = "127.0.0.1:1234";
connect(address).unwrap_or_else(|e| error!("{}", e));
}
/**
* 与指定的IP地址、端口号(所标识的进程)建立TCP连接
*/
pub fn connect(address: &str) -> Result<(), failure::Error> {
let mut stream = TcpStream::connect(address)?; // ①
loop {
// 将输入的数据通过套接字发送给服务器
let mut input = String::new(); // ②
io::stdin().read_line(&mut input)?;
stream.write_all(input.as_bytes())?; // ③
// 输出通过套接字接收到的数据
let mut reader = BufReader::new(&stream);
let mut buffer = Vec::new();
reader.read_until(b'\n', &mut buffer)?;
print!("{}", str::from_utf8(&buffer)?); // ④
}
}
TcpStream::connect()
①用于与指定的地址通过三次握手建立TCP连接。由于网络中传输的都是字节流,所以输入字符串②在发送之前必须转换成字节切片(byte slice, &[u8]
)③。反过来,对于接收到的字节切片,需要通过str::from_utf8()
将其转换为字符串切片(&str
)④。
&[u8]与&str的异同
-
相同点
- 二者都是由一个或多个字节(bytes)构成的
-
不同点
- 并不是所有的字节切片(byte slices,
&[8]
)都是有效的字符串切片(string slices,&str
),因为字符串切片必须是有效的UTF-8的字节序列,例如
// https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c71f7293d16b081d4f3cd9de39ea6883 fn main() { // 汉字“錆”的UTF-8编码是:0xE9 0x8C 0x86 let array: [u8; 3] = [0xE9, 0x8C, 0x86]; // Slices can be used to borrow a section of an array // and have the type signature &[T]. // Slices can point to a section of an array. let byte_slice: &[u8] = &array[0..2]; // [0xE9, 0x8C]不是完整的UTF-8编码 println!("{:?}", byte_slice); // [233, 140] println!("{:?}", std::str::from_utf8(byte_slice)); // Err(Utf8Error ... let byte_slice: &[u8] = &array; println!("{:?}", byte_slice); // [233, 140] println!("{:?}", std::str::from_utf8(byte_slice)); // Ok("錆") }
- 并不是所有的字节切片(byte slices,
运行TCP Echo客户端
$ cargo run
welcome to techbookfest6!!! # 发送
welcome to techbookfest6!!! # 接收