起因
在学习Rust时,Rust语言圣经 3.6.7 # 实践应用:多线程Web服务器 todo 还没有写好,想着下雨天打孩子,闲着也是闲着,正好检验一下学习成果。
参考
这个程序最重要的结构就是TcpListener
pub struct TcpListener(_); //A TCP socket server, listening for connections.
重点关注其以下两个函数:
- 函数:pub fn bind<A: ToSocketAddrs>(addr: A) -> Result;
- 功能描述:创建一个新的
TcpListener,它将绑定到指定的地址。 端口号为0的绑定将要求OS为该侦听器分配端口。
返回的监听器已经准备好接受连接。
- 函数:pub fn incoming(&self) -> Incoming;
- 功能描述:返回连结接收的迭代器
多线程需要的函数
- pub fn try_clone(&self) -> Result
- 创建一个新的独立拥有的底层套接字句柄。返回的
TcpListener是对该对象引用的同一套接字的引用。两个句柄均可用于接受传入连接,并且在一个侦听器上设置的选项将影响另一个。
example
use std::net::{TcpListener, TcpStream};
fn handle_client(stream: TcpStream) {
// ...
}
fn main() -> std::io::Result<()> {
//绑定到 `127.0.0.1:80` 的TCP侦听器
let listener = TcpListener::bind("127.0.0.1:80")?;
// 接受连接并串行处理它们
for stream in listener.incoming() {
handle_client(stream?);
}
Ok(())
}
多线程Web服务器
use std::net::{TcpStream,TcpListener};
use std::thread;
use std::sync::{Arc,Mutex};
fn handle_client(_stream: TcpStream) {
println!("有一个链接");
}
fn main() {
let listener = Arc::new(Mutex::new(TcpListener::bind("127.0.0.1:8080").unwrap()));
let mut handles = Vec::with_capacity(3);
for _ in 0..3{
let listen = Arc::clone(&listener);
handles. push(thread::spawn(move || {
let listen = listen.lock().unwrap();
for stream in listen.incoming(){
handle_client(stream.unwrap());
}
}));
}
for handle in handles {
handle.join().unwrap();
}
}