Rust 网络编程实战:用 tokio 写并发 TCP 服务器并优雅关闭

test12026-10-181 次阅读

从 HTTP 框架退一步看原生 TCP

写业务大多直接用 axum/actix,但理解底层 TCP 有助于排查连接泄漏、背压与优雅关闭问题。tokio 的 TcpListener 配合 per-connection 的异步任务,可以很自然地支撑上万并发连接,而优雅关闭则靠信号 + JoinSet 把在途连接跑完。

一个会回显的并发服务器

// src/main.rs
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpListener;
use tokio::signal;

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let listener = TcpListener::bind("127.0.0.1:8080").await?;
    println!("listening on 127.0.0.1:8080");

    // JoinSet 统一持有所有连接任务,便于一起等待结束
    let mut handles = tokio::task::JoinSet::new();

    loop {
        tokio::select! {
            // 收到 Ctrl+C 后跳出 accept 循环,进入收尾
            _ = signal::ctrl_c() => {
                println!("shutting down, draining connections...");
                break;
            }
            accepted = listener.accept() => {
                let (mut socket, addr) = match accepted {
                    Ok(v) => v,
                    Err(_) => continue,
                };
                // 每连接派一个任务,互不影响
                handles.spawn(async move {
                    let mut buf = [0u8; 1024];
                    loop {
                        match socket.read(&mut buf).await {
                            Ok(0) => break,          // 对端关闭
                            Ok(n) => {
                                if socket.write_all(&buf[..n]).await.is_err() { break; }
                            }
                            Err(_) => break,
                        }
                    }
                    println!("disconnected: {addr}");
                });
            }
        }
    }

    // 等待所有在途连接自然结束,不强制 kill
    while handles.join_next().await.is_some() {}
    println!("bye");
    Ok(())
}

关键点拆解

  • tokio::select! 让"收信号"和"接新连接"两条路并发进行,信号一来立即停止接新客。
  • 每个连接独立 spawn,单连接阻塞不会拖垮整体;JoinSet 比手动存 JoinHandle 更好回收。
  • read 返回 0 表示对端已关闭,务必 break,否则会空转读。
  • 真要做广播或多客户端互发,把 socket 写端放进 Arc<Mutex<TcpStream>> 或用 tokio::sync::broadcast 频道。
T

test1

文章作者

从 HTTP 框架退一步看原生 TCP 写业务大多直接用 axum/actix,但理解底层 TCP 有助于排查连接泄漏...

分类
技术
发布时间
2026-10-18
字数
约 1975 字
阅读
1 次