本例子中,W貓將帶大家寫一個大家都寫過但是沒什么人用過的TCP ECHO軟件,作為本章的結(jié)尾。本程序僅作為實例程序,我個人估計也沒有人在實際的生活中去使用她。不過,作為標準庫的示例來說,已經(jīng)足夠。
首先,我們需要一個一個服務(wù)器端。
fn server<A: ToSocketAddrs>(addr: A) -> io::Result<()> {
// 建立一個監(jiān)聽程序
let listener = try!(TcpListener::bind(&addr)) ;
// 這個程序一次只需處理一個鏈接就好
for stream in listener.incoming() {
// 通過match再次解包 stream到
match stream {
// 這里匹配的重點是如何將一個mut的匹配傳給一個Result
Ok(mut st) => {
// 我們總是要求client端先發(fā)送數(shù)據(jù)
// 準備一個超大的緩沖區(qū)
// 當然了,在實際的生活中我們一般會采用環(huán)形緩沖來重復(fù)利用內(nèi)存。
// 這里僅作演示,是一種很低效的做法
let mut buf: Vec<u8> = vec![0u8; 1024];
// 通過try!方法來解包
// try!方法的重點是需要有特定的Error類型與之配合
let rcount = try!(st.read(&mut buf));
// 只輸出緩沖區(qū)里讀取到的內(nèi)容
println!("{:?}", &buf[0..rcount]);
// 回寫內(nèi)容
let wcount = try!(st.write(&buf[0..rcount]));
// 以下代碼實際上算是邏輯處理
// 并非標準庫的一部分了
if rcount != wcount {
panic!("Not Fully Echo!, r={}, w={}", rcount, wcount);
}
// 清除掉已經(jīng)讀到的內(nèi)容
buf.clear();
}
Err(e) => {
panic!("{}", e);
}
}
}
// 關(guān)閉掉Serve端的鏈接
drop(listener);
Ok(())
}
然后,我們準備一個模擬TCP短鏈接的客戶端:
fn client<A: ToSocketAddrs>(addr: A) -> io::Result<()> {
let mut buf = vec![0u8;1024];
loop {
// 對比Listener,TcpStream就簡單很多了
// 本次模擬的是tcp短鏈接的過程,可以看作是一個典型的HTTP交互的基礎(chǔ)IO模擬
// 當然,這個通訊里面并沒有HTTP協(xié)議 XD!
let mut stream = TcpStream::connect(&addr).unwrap();
let msg = "WaySLOG comming!".as_bytes();
// 避免發(fā)送數(shù)據(jù)太快而刷屏
thread::sleep_ms(100);
let rcount = try!(stream.write(&msg));
let _ = try!(stream.read(&mut buf));
println!("{:?}", &buf[0..rcount]);
buf.clear();
}
Ok(())
}
將我們的程序拼接起來如下:
use std::net::*;
use std::io;
use std::io::{Read, Write};
use std::env;
use std::thread;
fn server<A: ToSocketAddrs>(addr: A) -> io::Result<()> { .. }
fn client<A: ToSocketAddrs>(addr: A) -> io::Result<()> { .. }
fn main() {
let mut args = env::args();
args.next();
let action = args.next().unwrap();
if action == "s" {
server(&args.next().unwrap()).unwrap();
} else {
client(&args.next().unwrap()).unwrap();
}
}
各位可以自己試一下結(jié)果
寫網(wǎng)絡(luò)程序,注定了要處理各種神奇的條件和錯誤,定義自己的數(shù)據(jù)結(jié)構(gòu),粘包問題等都是需要我們?nèi)ヌ幚砗完P(guān)注的。相較而言,Rust本身在網(wǎng)絡(luò)方面的基礎(chǔ)設(shè)施建設(shè)并不盡如人意,甚至連網(wǎng)絡(luò)I/O都只提供了如上的block I/O ??赡芷鋱F隊更關(guān)注于語言基礎(chǔ)語法特性和編譯的改進,但其實,有著官方出品的這種網(wǎng)絡(luò)庫是非常重要的。同時,我也希望Rust能夠涌現(xiàn)出更多的網(wǎng)絡(luò)庫方案,讓Rust的明天更好更光明。