kcp-io
A Rust wrapper for the KCP protocol, providing safe bindings to the original C implementation and an async UDP communication layer based on tokio.
What is KCP?
KCP is a fast and reliable ARQ (Automatic Repeat reQuest) protocol that can reduce average latency by 30%–40% compared to TCP, at the cost of 10%–20% more bandwidth. It sits above the transport layer (UDP) and provides:
- ✅ Reliable, ordered delivery
- ✅ Automatic retransmission with configurable strategy
- ✅ Congestion control (optional)
- ✅ Stream mode and message mode
- ✅ No kernel dependency — runs entirely in user space
Features
This crate uses Cargo features to provide a layered architecture:
kcp-sys— Raw FFI bindings to the KCP C library (compiled from source viacc)kcp-core— Safe, idiomatic Rust wrapper around KCP withSendsupport (implieskcp-sys)kcp-tokio(default) — Fully asyncKcpStream+KcpListenerpowered by tokio, withAsyncRead/AsyncWritesupport (implieskcp-core)
Feature dependency chain: kcp-tokio → kcp-core → kcp-sys
Project Structure
kcp-io/
├── Cargo.toml # Single crate with feature flags
├── build.rs # Compiles KCP C code via cc crate
├── kcp/ # Original KCP C source
│ ├── ikcp.c
│ ├── ikcp.h
│ └── wrapper.h
├── src/
│ ├── lib.rs # Root module: feature-gated exports + re-exports
│ ├── sys.rs # Raw FFI bindings (feature: kcp-sys)
│ ├── core/ # Safe Rust API wrapper (feature: kcp-core)
│ │ ├── mod.rs
│ │ ├── kcp.rs # Kcp struct (safe wrapper around IKCPCB)
│ │ ├── config.rs # KcpConfig presets
│ │ └── error.rs # KcpError enum
│ └── tokio_rt/ # Async tokio integration (feature: kcp-tokio)
│ ├── mod.rs
│ ├── stream.rs # KcpStream (AsyncRead + AsyncWrite)
│ ├── listener.rs # KcpListener (accept incoming connections)
│ ├── session.rs # KcpSession (internal state machine)
│ ├── config.rs # KcpSessionConfig
│ └── error.rs # KcpTokioError
├── tests/ # Integration tests
├── benches/ # Criterion benchmarks
└── examples/ # Echo server & client
Quick Start
Add to your Cargo.toml:
[]
= "0.1"
= { = "1", = ["full"] }
Echo Server
use ;
async
Echo Client
use ;
async
Using AsyncRead / AsyncWrite
KcpStream implements Tokio's AsyncRead and AsyncWrite traits, so you can use it with any Tokio-compatible ecosystem:
use ;
use ;
async
Using Only the Core Layer
If you only need the safe KCP wrapper without async support:
[]
= { = "0.1", = false, = ["kcp-core"] }
use ;
use io;
let mut kcp = new.unwrap;
kcp.apply_config.unwrap;
kcp.send.unwrap;
kcp.update;
API Overview
tokio_rt module (default feature: kcp-tokio)
| Type | Description |
|---|---|
KcpStream |
Async KCP stream — implements AsyncRead + AsyncWrite |
KcpListener |
Accepts incoming KCP connections on a UDP socket |
KcpSessionConfig |
Runtime configuration (KCP params + session settings) |
KcpTokioError |
Error type for async operations |
KcpStream methods:
| Method | Description |
|---|---|
connect(addr, config) |
Connect to a remote KCP server |
connect_with_conv(addr, conv, config) |
Connect with a specific conversation ID |
send_kcp(data) |
Send data reliably |
recv_kcp(buf) |
Receive data |
conv() |
Get the conversation ID |
remote_addr() |
Get the remote address |
local_addr() |
Get the local address |
KcpListener methods:
| Method | Description |
|---|---|
bind(addr, config) |
Bind to a local address and start listening |
accept() |
Accept the next incoming connection |
local_addr() |
Get the listener's local address |
core module (feature: kcp-core)
| Type | Description |
|---|---|
Kcp |
Safe wrapper around the C IKCPCB struct |
KcpConfig |
Protocol configuration (nodelay, interval, resend, etc.) |
KcpError |
Error type for KCP operations |
sys module (feature: kcp-sys)
Direct bindings to all ikcp_* functions. You generally don't need to use this directly.
Configuration
Presets
| Preset | nodelay | interval | resend | nc | snd_wnd | rcv_wnd | Use Case |
|---|---|---|---|---|---|---|---|
default() |
off | 100ms | 0 | off | 32 | 128 | Conservative, low bandwidth |
normal() |
on | 40ms | 2 | off | 64 | 128 | Balanced latency/bandwidth |
fast() |
on | 10ms | 2 | on | 128 | 128 | Lowest latency, more bandwidth |
Custom Configuration
use KcpSessionConfig;
use KcpConfig;
use Duration;
let config = KcpSessionConfig ;
Stream Mode vs Message Mode
| Feature | Message Mode (default) | Stream Mode |
|---|---|---|
| Boundary | Preserves message boundaries | Byte stream (like TCP) |
| Large data | Limited by fragment count | Unlimited size |
| Small data | Each message is a packet | Merges small messages |
| Use case | Game packets, RPC | File transfer, bulk data |
Building
# Build (default features: kcp-tokio)
# Build with only core features
# Build in release mode
Requirements:
- Rust 1.85+ (2021 edition)
- A C compiler (MSVC on Windows, gcc/clang on Linux/macOS) — needed to compile
ikcp.c
Testing
# Run all tests (unit + integration + doc tests)
# Run only integration tests
# Run with logging
RUST_LOG=debug
Running Examples
# Terminal 1: Start the echo server
# Terminal 2: Run the echo client
Architecture
Client Side Server Side
┌──────────────────┐ ┌──────────────────┐
│ Application │ │ Application │
│ │ │ │
│ KcpStream │ │ KcpListener │
│ ├─ send_kcp() │ │ ├─ bind() │
│ ├─ recv_kcp() │ │ ├─ accept() │
│ └─ AsyncR/W │ │ └─ KcpStream │
├──────────────────┤ ├──────────────────┤
│ KcpSession │ │ KcpSession │
│ ├─ KCP engine │ │ ├─ KCP engine │
│ ├─ update timer │ │ ├─ mpsc channel │
│ └─ UdpSocket │ │ └─ (shared UDP) │
├──────────────────┤ ├──────────────────┤
│ core::Kcp │ │ core::Kcp │
│ └─ output cb ───┼── UDP packets ──▶ ──┼─ input() │
├──────────────────┤ ├──────────────────┤
│ sys (FFI) │ │ sys (FFI) │
│ └─ ikcp.c │ │ └─ ikcp.c │
└──────────────────┘ └──────────────────┘
│ │
└──────── UDP / Internet ────────────────┘
Key design decisions:
- Client sessions own their UDP socket directly (
RecvMode::Socket) - Server sessions receive packets via
mpsc::channelfrom the listener's shared socket (RecvMode::Channel) - The
KcpListenerruns a backgroundtokio::spawntask that multiplexes incoming UDP packets by(SocketAddr, conv)to the correct session channel KcpSessiondrivesikcp_update()during send/recv calls
Performance Characteristics
| Aspect | Details |
|---|---|
| Latency | 30–40% lower than TCP on lossy networks |
| Bandwidth | ~10–20% overhead vs raw UDP |
| CPU | Minimal — KCP is lightweight C code |
| Memory | One Kcp instance per session (~10 KB) |
| Concurrency | One KcpSession per connection, managed by tokio runtime |
License
MIT License. See LICENSE for details.