udp_server
udp_server
High-performance async UDP server framework built on Tokio. Each client address is an independent "peer" with its own channel — write one async handler, and the framework handles sockets, peer lifecycle, and timeout cleanup.
Features
- Multi-socket parallelism — binds one socket per CPU core via
SO_REUSEPORT(Unix), kernel load-balances packets. - Per-address peers — each remote
SocketAddrgets aUdpPeerwith a dedicated handler task. - Zero-copy data path — received packets are shared as reference-counted
Bytes; no data copying through the channel. - Lock-free peer map — concurrent
DashMapeliminates mutex contention between recv and cleanup paths. - Automatic peer expiry — optional idle timeout (configurable per second).
- Configurable socket buffers — tune send/recv buffer size via the builder API.
Installation
[]
= "1"
Quick Start
Echo Server
use LevelFilter;
use UdpServer;
async
With Shared State
The handler's third parameter T is user-defined state, cloned for each peer:
use Arc;
use UdpServer;
async
API
UdpServer::new(addr, handler)
Creates the server (resolves addr immediately, defers socket creation to start()). Handler signature:
Fn(UDPPeer, UdpReader, T) -> Future<Output = Result<(), Box<dyn Error>>>
| Type | Description |
|---|---|
UDPPeer (Arc<UdpPeer>) |
Handle to the remote peer. send(&[u8]) sends, get_addr() returns address, close() force-closes. |
UdpReader (UnboundedReceiver<io::Result<Bytes>>) |
Incoming packets as zero-copy Bytes. Err(TimedOut) signals peer eviction. |
The handler runs in its own Tokio task per peer; the peer is auto-removed when the handler completes or errors.
Builder
| Method | Description |
|---|---|
.set_peer_timeout_sec(n) |
Evict peers idle for more than n seconds. |
.set_buffer_size(n) |
Set socket send/recv buffer size in bytes (default ~17.8 MB). |
.start(inner) |
Bind sockets and start the server. Blocks until shutdown. |
Running the Examples
How It Works
new()resolves the address;start()createsNsockets bound to it (UnixN = num_cpus, WindowsN = 1).- Each socket runs a dedicated
recv_fromloop. Packets from new addresses spawn aUdpPeerand the user's handler. - Data moves through an unbounded channel as
Bytes(zero-copy); handlers read viareader.recv().await. - If timeout is configured, a background task scans every 1s and pushes
Err(TimedOut)into stale peer channels.
License
MIT or Apache-2.0, at your option.
udp_server
高性能异步 UDP 服务端框架,基于 Tokio 构建。每个客户端地址被抽象为独立 "peer" 并拥有自己的 channel —— 只需编写一个 async handler,框架负责 socket 管理、peer 生命周期和超时清理。
特性
- 多 socket 并行 — 利用
SO_REUSEPORT(Unix)绑定与 CPU 核数相同数量的 socket,由内核负载均衡分发。 - 按地址分 peer — 每个远端
SocketAddr独立一个UdpPeer和专属 handler 任务。 - 零拷贝数据路径 — 接收的数据包以引用计数
Bytes传递,channel 中无数据拷贝。 - 无锁 peer 表 — 并发
DashMap消除了 recv 和清理路径间的互斥锁竞争。 - 自动超时清理 — 可选空闲超时,秒级可配。
- 可配置缓冲区 — 通过 builder API 调整 socket 收发缓冲区大小。
安装
[]
= "1"
快速上手
Echo 服务端
use LevelFilter;
use UdpServer;
async
带共享状态
handler 的第三个泛型参数 T 是用户自定义的共享状态,每个 peer 任务启动时会 clone 一份:
use Arc;
use UdpServer;
async
API
UdpServer::new(addr, handler)
创建服务端(立即解析地址,延迟到 start() 才创建 socket)。handler 签名:
Fn(UDPPeer, UdpReader, T) -> Future<Output = Result<(), Box<dyn Error>>>
| 类型 | 说明 |
|---|---|
UDPPeer (Arc<UdpPeer>) |
远端 peer 句柄。send(&[u8]) 发送数据、get_addr() 获取地址、close() 强制关闭。 |
UdpReader (UnboundedReceiver<io::Result<Bytes>>) |
接收零拷贝 Bytes 数据包。超时被驱逐时收到 Err(TimedOut)。 |
handler 在独立 Tokio 任务中运行,future 完成或出错时自动清理 peer。
Builder
| 方法 | 说明 |
|---|---|
.set_peer_timeout_sec(n) |
空闲超过 n 秒的 peer 将被驱逐。 |
.set_buffer_size(n) |
设置 socket 收发缓冲区大小(字节),默认约 17.8 MB。 |
.start(inner) |
绑定 socket 并启动服务端,服务端关闭时返回。 |
运行示例
工作原理
new()解析地址;start()创建N个 socket 绑定到该地址(UnixN = CPU 核数,WindowsN = 1)。- 每个 socket 独立循环
recv_from。新地址到达时创建UdpPeer并 spawn handler。 - 数据以
Bytes(零拷贝)通过 unbounded channel 推送,handler 用reader.recv().await消费。 - 若开启超时,后台任务每秒扫描并将
Err(TimedOut)推入超时 peer 的 channel。
License
MIT / Apache-2.0 双协议授权。