| Crates.io | rust_tokio_kcp |
| lib.rs | rust_tokio_kcp |
| version | 0.2.4 |
| created_at | 2026-01-23 08:55:47.814764+00 |
| updated_at | 2026-01-25 14:06:21.724468+00 |
| description | A kcp implementation for tokio |
| homepage | |
| repository | https://github.com/hushuoyouli/rust_tokio_kcp |
| max_upload_size | |
| id | 2063879 |
| size | 332,330 |
一个基于 Tokio 的 KCP 协议实现,提供高性能、低延迟的可靠 UDP 传输。
rust_tokio_kcp 是一个在 Tokio 异步运行时上实现的 KCP (KCP Protocol) 库。KCP 是一个快速可靠协议,可以比 TCP 浪费 10%-20% 的带宽的代价,换取平均延迟降低 30%-40%,且最大延迟降低三倍的传输效果。
本项目完全兼容 kcp-go,支持加密、FEC 前向纠错等高级特性。
KcpStream 和 KcpListener 接口,类似 TcpStream 和 TcpListener在 Cargo.toml 中添加依赖:
[dependencies]
rust_tokio_kcp = "0.2.0"
tokio = { version = "1.37", features = ["net", "sync", "rt", "macros", "time"] }
默认启用 AES 加密。你也可以启用其他加密算法:
[dependencies]
rust_tokio_kcp = { version = "0.2.0", features = ["aes", "tea", "xtea"] }
支持的加密特性:
aes (默认) - AES-128/192/256 加密tea - TEA 加密xtea - XTEA 加密simple_xor - 简单 XOR 加密(需要 pbkdf2 和 sha1)blowfish - Blowfish 加密cast5 - CAST5 加密triple_des - 3DES 加密twofish - Twofish 加密salsa20 - Salsa20 流加密sm4 - SM4 国密算法use rust_tokio_kcp::{KcpConfig, KcpListener};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = KcpConfig::default();
let mut listener = KcpListener::bind(config, "127.0.0.1:8080").await?;
loop {
let (mut stream, _) = listener.accept().await?;
tokio::spawn(async move {
let mut buf = [0; 1024];
loop {
let n = stream.read(&mut buf).await.unwrap();
if n == 0 {
break;
}
stream.write_all(&buf[..n]).await.unwrap();
}
});
}
}
use rust_tokio_kcp::{KcpConfig, KcpStream};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use std::net::SocketAddr;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = KcpConfig::default();
let server_addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
let mut stream = KcpStream::connect(&config, server_addr).await?;
stream.write_all(b"Hello, KCP!").await?;
let mut buf = [0; 1024];
let n = stream.read(&mut buf).await?;
println!("Received: {}", String::from_utf8_lossy(&buf[..n]));
Ok(())
}
use rust_tokio_kcp::{KcpConfig, KcpNoDelayConfig, Aes128BlockCrypt};
use std::sync::Arc;
// 创建 AES-128 加密器
let key = b"1234567890123456"; // 16 字节密钥
let crypt = Arc::new(Aes128BlockCrypt::new(key)?) as Arc<dyn rust_tokio_kcp::BlockCrypt>;
// 配置 KCP
let mut config = KcpConfig::default();
config.nodelay = KcpNoDelayConfig::fastest(); // 启用最快模式
config.wnd_size = (1024, 1024); // 增大窗口大小
config.flush_write = true; // 立即刷新写入
config.flush_acks_input = true; // 立即刷新 ACK
config.fec_data_shards = 10; // 启用 FEC:10 个数据分片
config.fec_parity_shards = 3; // 3 个校验分片
config.stream = true; // 启用 stream 模式
config.crypt = Some(crypt); // 启用 AES-128 加密
Custom Mode 的核心特性:每个连接(通过 conv ID 标识)可以配置独立的 salt,实现连接级别的安全隔离。
这个特性特别适用于:
use rust_tokio_kcp::{KcpConfig, ListenerMode, KcpListener};
// 启用 Custom Mode
let mut config = KcpConfig::default();
config.listener_mode = ListenerMode::Custom;
let mut listener = KcpListener::bind(config, "127.0.0.1:8080").await?;
// 为不同的连接配置独立的 salt
// conv_id = 1 使用 salt1
listener.custom_mode_notify().add(1, b"salt-for-connection-1".to_vec()).await?;
// conv_id = 2 使用 salt2
listener.custom_mode_notify().add(2, b"salt-for-connection-2".to_vec()).await?;
// conv_id = 100 使用 salt3(可以是任意 u32 值)
listener.custom_mode_notify().add(100, b"another-salt-value".to_vec()).await?;
// 动态移除某个连接的 salt 配置
listener.custom_mode_notify().remove(1).await?;
客户端在连接时需要指定对应的 conv ID 和 salt:
use rust_tokio_kcp::{KcpConfig, KcpStream};
use std::net::SocketAddr;
let config = KcpConfig::default();
let server_addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
// 方式 1: 使用 customize_connect_with_conv 指定 conv 和 salt
let conv_id = 1; // 必须与服务器端配置的 conv_id 匹配
let salt = b"salt-for-connection-1".to_vec(); // 必须与服务器端配置的 salt 匹配
let mut stream = KcpStream::customize_connect_with_conv(&config, conv_id, server_addr, salt).await?;
// 方式 2: 使用已有的 UdpSocket 连接
let udp = UdpSocket::bind("0.0.0.0:0").await?;
let mut stream = KcpStream::customize_connect_with_socket(&config, udp, server_addr, salt).await?;
conv_map 维护 conv_id 到 salt 的映射关系// 服务器端
use rust_tokio_kcp::{KcpConfig, ListenerMode, KcpListener};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut config = KcpConfig::default();
config.listener_mode = ListenerMode::Custom;
let mut listener = KcpListener::bind(config, "127.0.0.1:8080").await?;
// 为不同租户配置不同的 salt
listener.custom_mode_notify().add(1001, b"tenant-a-salt".to_vec()).await?;
listener.custom_mode_notify().add(1002, b"tenant-b-salt".to_vec()).await?;
loop {
let (mut stream, addr) = listener.accept().await?;
tokio::spawn(async move {
// 每个连接使用其对应的 salt 进行通信
let mut buf = [0; 1024];
loop {
let n = stream.read(&mut buf).await.unwrap();
if n == 0 { break; }
stream.write_all(&buf[..n]).await.unwrap();
}
});
}
}
// 客户端(租户 A)
let conv_id = 1001;
let salt = b"tenant-a-salt".to_vec();
let mut stream = KcpStream::customize_connect_with_conv(&config, conv_id, server_addr, salt).await?;
重要提示:
use rust_tokio_kcp::{KcpConfig, KcpNoDelayConfig};
let mut config = KcpConfig::default();
// 使用最快模式(低延迟,适合游戏等实时应用)
config.nodelay = KcpNoDelayConfig::fastest();
// 或使用普通模式(平衡延迟和带宽)
config.nodelay = KcpNoDelayConfig::normal();
// 增大窗口大小以提高吞吐量
config.wnd_size = (1024, 1024);
// 启用立即刷新以提高响应速度
config.flush_write = true;
config.flush_acks_input = true;
本项目采用共享 UdpSocket 的设计:
Arc<UdpSocket> 实现零成本共享| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
mtu |
usize |
1400 | 最大传输单元 |
nodelay |
KcpNoDelayConfig |
normal() |
延迟配置 |
wnd_size |
(u16, u16) |
(256, 256) | 发送/接收窗口大小 |
stream |
bool |
false | 是否启用流模式 |
fec_data_shards |
usize |
0 | FEC 数据分片数(0 表示禁用) |
fec_parity_shards |
usize |
0 | FEC 校验分片数(0 表示禁用) |
crypt |
Option<Arc<dyn BlockCrypt>> |
None | 加密算法 |
listener_mode |
ListenerMode |
Normal |
监听器模式:Normal - 标准 CRC32 校验;Custom - 每个连接独立配置 salt(见 Custom Mode 章节) |
| 参数 | 类型 | 说明 |
|---|---|---|
nodelay |
bool |
是否启用 NoDelay |
interval |
i32 |
内部更新间隔(毫秒) |
resend |
i32 |
快速重传触发阈值 |
nc |
bool |
是否禁用拥塞控制 |
预设配置:
KcpNoDelayConfig::fastest() - 最快模式:nodelay=true, interval=10ms, resend=2, nc=trueKcpNoDelayConfig::normal() - 普通模式:nodelay=false, interval=40ms, resend=0, nc=false项目提供了多个示例:
examples/server.rs - 完整的服务器示例,支持加密和 FECexamples/client.rs - 客户端示例examples/benchmark_client.rs - 性能测试客户端examples/test_client.rs - 测试客户端运行示例:
# 运行服务器
cargo run --example server --features aes
# 运行客户端
cargo run --example client --features aes
本项目完全兼容 kcp-go,可以:
测试兼容性:
# 启动 Go 服务器(在 kcp-server 目录)
cd kcp-server
go run server.go
# 运行 Rust 客户端
cargo run --example client --features aes
当前实现中存在以下锁:
在高并发场景下,建议:
parking_lot::Mutex 替代标准库的 Mutex(如果性能成为瓶颈)wnd_sizeKcpNoDelayConfig::fastest()flush_write 和 flush_acks_inputMIT License
本项目基于 tokio_kcp 项目进行修改和扩展,并参考了 kcp-go 的实现。