A crypto-secure Reliable-UDP library for Golang with FEC support.
A crypto-secure Reliable-UDP library for Golang with FEC support.
kcp-go is a Reliable-UDP library for golang.
This library provides smooth, resilient, ordered, error-checked, and anonymous stream delivery over UDP packets. It has been deployed across millions of devices—from low-end MIPS routers to high-end servers—across various applications, including online games, live broadcasting, file synchronization, and network acceleration.
For complete documentation, see the associated Godoc.
kcp.flush() loops through the send queue for retransmission checking every 20 ms.
I wrote a benchmark comparing sequential loops through a slice and a container/list here:
BenchmarkLoopSlice-4 2000000000 0.39 ns/op
BenchmarkLoopList-4 100000000 54.6 ns/op
The list structure introduces heavy cache misses compared to the slice, which offers better locality. For 5,000 connections with a 32-window size and a 20 ms interval, using a slice costs 6 μs (0.03% CPU) per kcp.flush(), whereas using a list costs 8.7 ms (43.5% CPU).
Timing is critical for the RTT estimator. Inaccurate timing leads to false retransmissions in KCP, but calling time.Now() costs 42 cycles (10.5 ns on a 4 GHz CPU, 15.6 ns on my MacBook Pro 2.7 GHz).
The benchmark for time.Now() is here:
BenchmarkNow-4 100000000 15.6 ns/op
In kcp-go, after each kcp.output() function call, the current clock time is updated upon return. For a single kcp.flush() operation, the current time is queried from the system once. For 5,000 connections, this costs 5000 × 15.6 ns = 78 μs (a fixed cost when no packets need to be sent). For 10 MB/s data transfer with a 1400 MTU, kcp.output() is called approximately 7,500 times, costing 117 μs for time.Now() per second.
Primary memory allocation is performed from a global buffer pool, xmit.Buf. In kcp-go, when bytes need to be allocated, they are obtained from this pool, which returns a fixed-capacity 1500 bytes (mtuLimit). The rx queue, tx queue, and FEC queue all receive bytes from this pool and return them after use to prevent unnecessary zeroing of bytes. The pool mechanism maintains a high watermark for slice objects, allowing these in-flight objects to survive periodic garbage collection while also being able to return memory to the runtime when idle.
kcp-go ships with built-in packet encryption powered by various block encryption algorithms and operates in Cipher Feedback Mode. For each packet to be sent, the encryption process begins by encrypting a nonce from the system entropy, ensuring that encryption of the same plaintext never produces the same ciphertext.
The contents of packets are completely anonymous with encryption, including the headers (FEC, KCP), checksums, and payload. Note that regardless of which encryption method you choose at the upper layer, if you disable encryption, the transmission will be insecure because the header is plaintext and susceptible to tampering, such as jamming the sliding window size, round-trip time, FEC properties, and checksums. AES-128 is recommended for minimal encryption, as modern CPUs feature AES-NI instructions and perform better than salsa20 (see the table above).
Other possible attacks on kcp-go include:
fastack is triggered, without waiting for the fixed interval.interval.
In high-speed networks, this acts as a higher-frequency "clock signal," potentially boosting unidirectional transmission speed by approximately 6x. For instance, if a batch takes only 1.5ms to process on a high-speed link but still adheres to a fixed 10ms transmission cycle, the actual throughput would be limited to 1/6 of the potential.snd_wnd is large, causing the kernel to drop packets. While difficult to implement in user space, a usable version has been achieved, allowing user-space echo to stabilize above 100MB/s.snd_buf ringbuffer) to ensure good cache coherency. Queues must not be too long; otherwise, traversal costs introduce extra latency. In high-speed networks, the buffer corresponding to BDP should be kept smaller to minimize latency from data structures. Note that the current KCP structure has O(n) complexity for RTO; changing it to O(1) would require significant refactoring.Ultimately, nothing is more critical in a transmission system than the clock (real-time performance).
postProcess/packetInput path, so parity shards are generated and consumed without extra goroutines or lock contention.KCP.Input, minimizing reordering and retransmission storms.…
…
…
…
Control messages like SYN/FIN/RST in TCP are not defined in KCP. You need a keepalive/heartbeat mechanism at the application level. A practical example is to use a multiplexing protocol over the session, such as smux (which has an embedded keepalive mechanism).
Q: I'm handling >5K connections on my server, and the CPU utilization is very high.
A: A standalone agent or gate server for running kcp-go is recommended, not only to reduce CPU utilization but also to improve the precision of RTT measurements (timing), which indirectly affects retransmission. Increasing the update interval with SetNoDelay, such as conn.SetNoDelay(1, 40, 1, 1), will dramatically reduce system load but may lower performance.
Q: When should I enable FEC?
A: Forward error correction is critical for long-distance transmission because packet loss incurs a significant time penalty. In the complex packet routing networks of the modern world, round-trip time-based loss checks are not always efficient. The significant devia
No open issues yet, or sync has not completed.