tcpserver
English
A lightweight, extensible async TCP server framework built on Tokio — with TLS support, backpressure, and a clean builder API.
- MSRV: Rust 1.75+
- Async runtime: Tokio
- Concurrency model: Actor-based (via aqueue) — lock-free interior mutability
- Stream extensibility: Plain TCP, TLS (OpenSSL), or any
AsyncRead + AsyncWritestream - Backpressure: Optional connection limit via
Semaphore - Related crate: tcpclient — matching TCP client framework
Features
| Feature | Description |
|---|---|
| 🔌 Builder API | Chainable Builder / FromStdBuilder with compile-time type safety |
| 🔁 Stream Init | Transform raw TcpStream into any AsyncRead + AsyncWrite (TLS, GZIP, …) |
| 🔒 TLS | Optional OpenSSL-based TLS via tls feature flag |
| ⚡ TCP_NODELAY | Disable Nagle's algorithm for low-latency scenarios |
| 🚦 Connection Limit | Semaphore-based backpressure — block accept when at capacity |
| 🎯 Connect Filter | Per-connection callback to accept or reject by SocketAddr |
| 📦 Zero-cost generics | All type parameters resolved at compile time; use Arc<dyn ITCPServer<T>> for type erasure |
Project Structure
src/
├── lib.rs # Crate root, re-exports
├── tcpserver.rs # TCPServer + ITCPServer trait
├── peer.rs # TCPPeer + IPeer trait
├── builder.rs # Builder (bind by address)
├── builder_std.rs # FromStdBuilder (use existing TcpListener)
└── error.rs # Error types
examples/
├── echo_server.rs # Plain TCP echo server
├── echo_server_from_std.rs # Echo server from std TcpListener
├── echo_client.rs # Echo client (for testing)
├── ssl_server.rs # TLS echo server (requires --features tls)
└── test_ssl_client.rs # TLS client (requires --features tls)
Quick Start
Add Dependencies
[]
= "2"
= { = "1", = ["full"] }
= "1"
Optional Features
# TLS support
= { = "2", = ["tls"] }
Echo Server
The input closure receives (ReadHalf<C>, Arc<Actor<TCPPeer<C>>>, T) where T is your per-connection token.
use Result;
use Arc;
use ;
use AsyncReadExt;
async
Run it:
With TCP_NODELAY + Connection Limit
let server = new
.set_nodelay // disable Nagle's algorithm
.set_max_connections // max concurrent connections (0 = unlimited)
.set_stream_init
.set_input_event
.build
.await;
Using an Existing TcpListener (socket options)
When you need SO_REUSEADDR or other socket options before binding:
use ;
use SocketAddr;
use FromStdBuilder;
let socket = new?;
socket.set_reuse_address?;
let addr: SocketAddr = "0.0.0.0:5555".parse?;
socket.bind?;
socket.listen?;
let server = new
.set_stream_init
.set_input_event
.build
.await;
Run:
TLS Server
Requires --features tls and OpenSSL development libraries.
// See examples/ssl_server.rs for the full example
let acceptor = build_ssl_acceptor; // SslAcceptor with cert + key
let server = new
.set_stream_init
.set_input_event
.build
.await;
Run:
The matching TLS client:
API Reference
Builder / FromStdBuilder
| Method | Description |
|---|---|
new(addr) / new(listener) |
Create a builder |
set_input_event(f) |
Required. Called for each connection — receives reader, peer handle, and token |
set_stream_init(f) |
Required. Transform TcpStream → target stream type |
set_connect_event(f) |
Optional. fn(SocketAddr) -> bool — return false to reject |
set_nodelay(bool) |
Enable TCP_NODELAY. Default: false |
set_max_connections(n) |
Max concurrent connections. 0 = unlimited. Default: 0 |
build() |
Finalize and create the server. Panics if required fields are missing |
IPeer Trait
The peer handle passed to your input handler. All methods are async and thread-safe (backed by aqueue::Actor).
| Method | Description |
|---|---|
addr() -> SocketAddr |
Remote address |
is_disconnect() -> Result<bool> |
Check if the peer is disconnected |
send(buf) -> Result<usize> |
Send bytes, returns count written |
send_all(buf) -> Result<()> |
Send all bytes, then flush |
send_ref(&[u8]) -> Result<usize> |
Send from a byte slice reference |
send_all_ref(&[u8]) -> Result<()> |
Send-all from a byte slice reference |
flush() -> Result<()> |
Flush the write buffer |
disconnect() -> Result<()> |
Shutdown the write half |
ITCPServer<T> Trait
Type-erased server handle. T is your per-connection token type.
| Method | Description |
|---|---|
start(token) -> Result<JoinHandle<...>> |
Start accepting, returns a handle |
start_block(token) -> Result<()> |
Start accepting and block until the server exits |
Examples
# Plain TCP echo
# From existing TcpListener (with socket options)
# TLS server + client (requires OpenSSL)
Related Projects
- tcpclient — Matching async TCP client framework
License
Licensed under either of MIT or Apache-2.0 at your option.
中文
基于 Tokio 的轻量级异步 TCP 服务框架 — 支持 TLS、背压控制、链式 Builder API。
- MSRV: Rust 1.75+
- 异步运行时: Tokio
- 并发模型: Actor 模式(基于 aqueue)— 无锁内部可变性
- 流扩展: 纯 TCP、TLS(OpenSSL)、或任意
AsyncRead + AsyncWrite流 - 背压: 可选连接数限制(
Semaphore) - 相关库: tcpclient — 配套 TCP 客户端框架
功能特性
| 特性 | 说明 |
|---|---|
| 🔌 Builder API | 链式 Builder / FromStdBuilder,编译期类型安全 |
| 🔁 流初始化 | 将原始 TcpStream 转换为任意 AsyncRead + AsyncWrite(TLS、GZIP等) |
| 🔒 TLS | 可选 OpenSSL TLS,通过 tls feature 开启 |
| ⚡ TCP_NODELAY | 关闭 Nagle 算法,降低小包延迟 |
| 🚦 连接数限制 | 基于 Semaphore 的背压 — 达到上限时阻塞 accept |
| 🎯 连接过滤器 | 按 SocketAddr 决定接受或拒绝连接 |
| 📦 零成本泛型 | 编译期解析所有类型参数;用 Arc<dyn ITCPServer<T>> 擦除类型 |
项目结构
src/
├── lib.rs # crate 根,重导出
├── tcpserver.rs # TCPServer + ITCPServer trait
├── peer.rs # TCPPeer + IPeer trait
├── builder.rs # Builder(按地址绑定)
├── builder_std.rs # FromStdBuilder(使用已有 TcpListener)
└── error.rs # 错误类型
examples/
├── echo_server.rs # 纯 TCP echo 服务器
├── echo_server_from_std.rs # 从 std TcpListener 构建
├── echo_client.rs # Echo 客户端(测试用)
├── ssl_server.rs # TLS echo 服务器(需 --features tls)
└── test_ssl_client.rs # TLS 客户端(需 --features tls)
快速开始
添加依赖
[]
= "2"
= { = "1", = ["full"] }
= "1"
可选功能
# TLS 支持
= { = "2", = ["tls"] }
Echo 服务器
输入闭包签名为 (ReadHalf<C>, Arc<Actor<TCPPeer<C>>>, T),其中 T 是自定义的每连接令牌。
use Result;
use Arc;
use ;
use AsyncReadExt;
async
运行:
配置 TCP_NODELAY + 连接数限制
let server = new
.set_nodelay // 关闭 Nagle 算法
.set_max_connections // 最大并发连接数(0 = 不限制)
.set_stream_init
.set_input_event
.build
.await;
使用已有 TcpListener(设置 socket 选项)
当需要在 bind 之前设置 SO_REUSEADDR 等 socket 选项时:
use ;
use SocketAddr;
use FromStdBuilder;
let socket = new?;
socket.set_reuse_address?;
let addr: SocketAddr = "0.0.0.0:5555".parse?;
socket.bind?;
socket.listen?;
let server = new
.set_stream_init
.set_input_event
.build
.await;
运行:
TLS 服务器
需要 --features tls 和 OpenSSL 开发库。
// 完整示例见 examples/ssl_server.rs
let acceptor = build_ssl_acceptor; // 配置了证书和密钥的 SslAcceptor
let server = new
.set_stream_init
.set_input_event
.build
.await;
运行:
配套 TLS 客户端:
API 参考
Builder / FromStdBuilder
| 方法 | 说明 |
|---|---|
new(addr) / new(listener) |
创建 Builder |
set_input_event(f) |
必填。 每连接调用 — 接收 reader、peer 句柄和 token |
set_stream_init(f) |
必填。 将 TcpStream 转换为目标流类型 |
set_connect_event(f) |
可选。fn(SocketAddr) -> bool — 返回 false 拒绝连接 |
set_nodelay(bool) |
启用 TCP_NODELAY。默认:false |
set_max_connections(n) |
最大并发连接数。0 = 不限制。默认:0 |
build() |
构建服务器。缺少必填字段会 panic |
IPeer Trait
传给输入处理器的 peer 句柄。所有方法均为异步且线程安全(基于 aqueue::Actor)。
| 方法 | 说明 |
|---|---|
addr() -> SocketAddr |
远端地址 |
is_disconnect() -> Result<bool> |
检查是否已断开 |
send(buf) -> Result<usize> |
发送数据,返回已写入字节数 |
send_all(buf) -> Result<()> |
发送全部数据并 flush |
send_ref(&[u8]) -> Result<usize> |
从字节切片引用发送 |
send_all_ref(&[u8]) -> Result<()> |
从字节切片引用发送全部 |
flush() -> Result<()> |
刷新写缓冲区 |
disconnect() -> Result<()> |
关闭写半部 |
ITCPServer<T> Trait
类型擦除的服务器句柄。T 是自定义的每连接令牌类型。
| 方法 | 说明 |
|---|---|
start(token) -> Result<JoinHandle<...>> |
启动 accept,返回句柄 |
start_block(token) -> Result<()> |
启动 accept 并阻塞直到服务器退出 |
示例
# 纯 TCP echo
# 从已有 TcpListener(带 socket 选项)
# TLS 服务器 + 客户端(需要 OpenSSL)
相关项目
- tcpclient — 配套异步 TCP 客户端框架
许可证
采用 MIT 或 Apache-2.0 双许可证,任选其一。