本例子用Rust實現一個基於TCP的echo的服務端和客戶端的程序,用Rust演示簡單的網絡程序。
服務端
服務端實現類似於我們之前寫過的http服務端的實現。涉及到的知識點主要是std::io和std::net。代碼如下:
<code>use std::io::{Error, Read, Write}; use std::net::{TcpListener, TcpStream}; use std::thread; use std::time; fn handle_client(mut stream: TcpStream) -> Result{ let mut buf = [0; 512]; for _ in 0..1000 { let bytes_read = stream.read(&mut buf)?; if bytes_read == 0 { return Ok(()); } stream.write(&buf[..bytes_read])?; thread::sleep(time::Duration::from_secs(1 as u64)); } Ok(()) } fn main() -> std::io::Result { let listener = TcpListener::bind("127.0.0.1:8080")?; let mut thread_vec: Vec> = Vec::new(); for stream in listener.incoming() { let stream = stream.expect("failed!"); let handle = thread::spawn(move || { handle_client(stream) .unwrap_or_else(|error| eprintln!("{:?}", error)); }); thread_vec.push(handle); } for handle in thread_vec { handle.join().unwrap(); } Ok(()) }/<code>
客戶端
在我們以前演示的webserver程序中,我們是使用的瀏覽器來作為客戶端發出請求,本例子中,我們用Rust實現客戶端。源碼如下:
<code>use std::io::{self, prelude::*, BufReader, Write}; use std::net::TcpStream; use std::str; fn main() -> std::io::Result { let mut stream = TcpStream::connect("127.0.0.1:8080")?; for _ in 0..10 { let mut input = String::new(); io::stdin() .read_line(&mut input) .expect("Failed to read from stdin"); stream .write(input.as_bytes()) .expect("Failed to write to stream"); let mut reader = BufReader::new(&stream); let mut buffer: Vec = Vec::new(); reader .read_until(b'\n', &mut buffer) .expect("Could not read into buffer"); println!("{}", str::from_utf8(&buffer).expect("Could not write buffer as string")); println!(""); } Ok(()) }/<code>
知識點總結
在本例子中,我們使用了io庫讀取一些內容。
- 從標準輸入讀取BufRead是一種類型的Reader,它具有一個內部緩衝區,允許它執行其它讀取方式。例如,在不使用緩衝區的情況下,逐行讀取效率低下,因此,如果要逐行讀取,則需要BufRead,它包括read_line方法和行迭代器。標準輸入實現了BufRead,例子如下:use std::io; use std::io::prelude::*; let stdin = io::stdin(); for line in stdin.lock().lines() { println!("{}", line.unwrap()); }
- BufReaderBufReader每次讀取較多的內容,並且在內存中維護讀取的結果,減少Read系統調用的次數,提高效率。BufReader使用例子:use std::io::prelude::*; use std::io::BufReader; use std::fs::File; fn main() -> std::io::Result { let f = File::open("log.txt")?; let mut reader = BufReader::new(f); let mut line = String::new(); let len = reader.read_line(&mut line)?; println!("First line is {} bytes long", len); Ok(()) }