Rust是否有类似Node.js创建持久TCP服务器的等效功能?
Rust 实现类似 Node.js 的 TCP 服务器
问题描述
我希望在 Rust 中实现与 Node.js 如下代码类似的 TCP 服务器功能:
const server = createServer(socket => { socket.on("data", (data) => { }); socket.on("close", () => log("closed")); }); server.on("error", err => { throw err; }); server.on("close", () => log("shutdown"));
我尝试使用了 Rust 的 TcpListener,但发现它似乎不具备我需要的全部功能,且连接无法保持持久,无法获取客户端的握手数据包。请问:
- Rust 的
TcpListener会自动关闭连接吗? - Rust 中是否有我不知道的持久化 TCP 工具?
解答
关于 TcpListener 是否自动关闭连接
TcpListener 本身不会自动关闭连接。连接关闭的常见原因包括:
- 处理连接的代码执行完毕,
TcpStream因 Rust 所有权机制被销毁,触发 TCP 连接关闭流程 - 客户端主动断开连接
- 网络异常导致连接中断
你遇到的连接无法持久,大概率是因为处理单个连接的函数执行完成后,TcpStream 被自动释放,进而关闭了连接。要保持连接,需要在处理函数中持续监听该 TcpStream 的数据。
用标准库实现持久化 TCP 服务器
TcpListener 完全可以满足需求,不需要额外工具。以下是对应功能的示例代码:
use std::io::{Read, Write}; use std::net::{TcpListener, TcpStream}; use std::thread; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use ctrlc; fn handle_client(mut stream: TcpStream, server_running: Arc<AtomicBool>) { let mut buffer = [0; 1024]; // 循环读取数据,维持连接 while server_running.load(Ordering::Relaxed) { match stream.read(&mut buffer) { Ok(0) => { // 读取0字节代表客户端主动关闭连接 println!("closed"); break; } Ok(n) => { // 这里处理收到的数据,示例仅打印 println!("Received {} bytes: {:?}", n, &buffer[..n]); // 如需回复客户端,可调用 stream.write_all(&buffer[..n]) } Err(e) => { eprintln!("读取数据出错: {}", e); break; } } } } fn main() { let listener = TcpListener::bind("127.0.0.1:8080").expect("绑定地址失败"); let server_running = Arc::new(AtomicBool::new(true)); let running_clone = server_running.clone(); // 处理Ctrl+C关闭信号 ctrlc::set_handler(move || { running_clone.store(false, Ordering::Relaxed); println!("shutdown"); std::process::exit(0); }).expect("设置信号处理器失败"); println!("服务器监听 127.0.0.1:8080"); // 循环接受新连接,每个连接启动独立线程处理 for stream in listener.incoming() { match stream { Ok(stream) => { let running = server_running.clone(); thread::spawn(move || { handle_client(stream, running); }); } Err(e) => { eprintln!("接受连接出错: {}", e); if !server_running.load(Ordering::Relaxed) { break; } } } } }
代码关键点说明
- 通过
listener.incoming()循环接受新连接,每个连接启动单独线程处理,避免阻塞主线程 handle_client函数中用循环持续读取TcpStream数据,只要循环不终止,TcpStream就不会被销毁,连接得以保持- 用
AtomicBool标记服务器运行状态,处理关闭信号时通知所有连接线程退出 - 读取到0字节时,判定客户端主动关闭连接,退出循环释放
TcpStream
关于握手数据包
如果是指TCP三次握手后的应用层握手,TcpListener 接受连接后,TcpStream 已经完成TCP三次握手,你可以直接在 handle_client 函数开头读取应用层的握手数据包即可。
内容的提问来源于stack exchange,提问作者May
相关产品推荐
相关产品推荐

