mirror of
https://github.com/skywind3000/kcp.git
synced 2026-08-19 22:23:28 +08:00
Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8004f7eba5 | ||
|
|
f4f3a89cc6 | ||
|
|
db4526a01b | ||
|
|
ec72e34715 | ||
|
|
fbf73d19a1 | ||
|
|
7f9805887b | ||
|
|
8f706ad697 | ||
|
|
b4a0aba445 | ||
|
|
bfe542b9ec | ||
|
|
ecafc2b299 | ||
|
|
fcd439304f | ||
|
|
bb9416a705 | ||
|
|
0d85027370 | ||
|
|
8e7f855a1f | ||
|
|
94385a10f8 | ||
|
|
7440cdaeb7 | ||
|
|
924a190ee0 | ||
|
|
7a878bf358 | ||
|
|
49bea97d33 | ||
|
|
f2aa30ea21 | ||
|
|
c0cb6ab3ac | ||
|
|
10ee2b30c8 | ||
|
|
62b38db385 | ||
|
|
fb3ccde6c0 | ||
|
|
b6b86cbb82 | ||
|
|
9bda4ac0b1 | ||
|
|
2c77d64e68 | ||
|
|
fe96c9fa8a | ||
|
|
5264734c81 | ||
|
|
9e662609be | ||
|
|
acd7983719 | ||
|
|
86344664db | ||
|
|
5481f0397f | ||
|
|
2a80825d37 | ||
|
|
f482028f24 | ||
|
|
3c9fd966f9 | ||
|
|
6900c9128e | ||
|
|
fe306fc4ec | ||
|
|
d06a81a28a | ||
|
|
f553df7afc | ||
|
|
db793e8108 | ||
|
|
58139efbba | ||
|
|
95dad07646 | ||
|
|
7e8edde201 | ||
|
|
78090be86e | ||
|
|
6de8bbf271 | ||
|
|
a9feff68b3 | ||
|
|
77a4f85ae6 | ||
|
|
e5a9c12ae9 | ||
|
|
2ddef54c08 | ||
|
|
d4b8fa8709 | ||
|
|
57bd697cfc | ||
|
|
0ea090bdea | ||
|
|
944cbaa411 | ||
|
|
28c802e6a6 | ||
|
|
2fffb01d8b | ||
|
|
cbb19b76c5 | ||
|
|
d6829263fe | ||
|
|
5117840a69 | ||
|
|
2163e05b13 | ||
|
|
ff195afe03 | ||
|
|
67ee559e76 | ||
|
|
1ca75754cf | ||
|
|
6b9c2b683e | ||
|
|
bab2b09391 | ||
|
|
ce02fbd433 | ||
|
|
bf616efb43 | ||
|
|
eec3b39516 | ||
|
|
a1ca12aadc | ||
|
|
14c6beb88d | ||
|
|
38e0c9366e | ||
|
|
53e568bd3b | ||
|
|
700e2a8161 | ||
|
|
9158f84781 |
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
*.o
|
||||
*.obj
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
*.ncb
|
||||
|
||||
/.vscode/*
|
||||
/.idea/*
|
||||
/.DS_Store
|
||||
/.env
|
||||
/build/*
|
||||
|
||||
@@ -1,18 +1,49 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 4.0)
|
||||
|
||||
project(kcp LANGUAGES C)
|
||||
|
||||
include(CTest)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
add_library(kcp STATIC ikcp.c)
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
|
||||
install(FILES ikcp.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
if(BUILD_SHARED_LIBS AND WIN32)
|
||||
set(exports_def_file "${CMAKE_CURRENT_BINARY_DIR}/exports.def")
|
||||
set(exports_def_contents
|
||||
"EXPORTS
|
||||
ikcp_create
|
||||
ikcp_release
|
||||
ikcp_setoutput
|
||||
ikcp_recv
|
||||
ikcp_send
|
||||
ikcp_update
|
||||
ikcp_check
|
||||
ikcp_input
|
||||
ikcp_flush
|
||||
ikcp_peeksize
|
||||
ikcp_setmtu
|
||||
ikcp_wndsize
|
||||
ikcp_waitsnd
|
||||
ikcp_nodelay
|
||||
ikcp_log
|
||||
ikcp_allocator
|
||||
ikcp_getconv
|
||||
")
|
||||
|
||||
file(WRITE "${exports_def_file}" "${exports_def_contents}")
|
||||
add_library(kcp ikcp.c "${exports_def_file}")
|
||||
else()
|
||||
add_library(kcp ikcp.c)
|
||||
endif()
|
||||
|
||||
install(FILES ikcp.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
|
||||
install(TARGETS kcp
|
||||
EXPORT kcp-targets
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
|
||||
install(EXPORT kcp-targets
|
||||
@@ -21,11 +52,11 @@ install(EXPORT kcp-targets
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/kcp
|
||||
)
|
||||
|
||||
if (BUILD_TESTING)
|
||||
if(BUILD_TESTING)
|
||||
enable_language(CXX)
|
||||
|
||||
|
||||
add_executable(kcp_test test.cpp)
|
||||
if(MSVC AND NOT (MSVC_VERSION LESS 1900))
|
||||
target_compile_options(kcp_test PRIVATE /utf-8)
|
||||
endif()
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
81
README.en.md
81
README.en.md
@@ -1,50 +1,69 @@
|
||||
KCP - A Fast and Reliable ARQ Protocol
|
||||
======================================
|
||||
|
||||
[![Powered][2]][1] [![Build Status][4]][5]
|
||||
[![Powered][3]][1]
|
||||
[![GitHub license][6]][7]
|
||||
[](#backers)
|
||||
[](#sponsors)
|
||||
|
||||
[1]: https://github.com/skywind3000/kcp
|
||||
[2]: http://skywind3000.github.io/word/images/kcp.svg
|
||||
[3]: https://raw.githubusercontent.com/skywind3000/kcp/master/kcp.svg
|
||||
[2]: https://github.com/skywind3000/kcp/raw/master/kcp.svg
|
||||
[3]: https://github.com/skywind3000/kcp/raw/master/kcp.svg
|
||||
[4]: https://api.travis-ci.org/skywind3000/kcp.svg?branch=master
|
||||
[5]: https://travis-ci.org/skywind3000/kcp
|
||||
|
||||
[6]: https://img.shields.io/badge/license-MIT-blue.svg
|
||||
[7]: https://github.com/skywind3000/kcp/blob/master/LICENSE
|
||||
|
||||
# Introduction
|
||||
|
||||
KCP is a fast and reliable protocol that can achieve the transmission effect of a reduction of the average latency by 30% to 40% and reduction of the maximum delay by a factor of three, at the cost of 10% to 20% more bandwidth wasted than TCP. It is implemented by using the pure algorithm, and is not responsible for the sending and receiving of the underlying protocol (such as UDP), requiring the users to define their own transmission mode for the underlying data packet, and provide it to KCP in the way of callback. Even the clock needs to be passed in from the outside, without any internal system calls.
|
||||
**KCP** is a high-performance, reliable transport protocol designed to significantly reduce latency compared to traditional TCP. It can achieve a **30–40% reduction in average latency** and up to three times lower maximum delay, _costing 10–20% additional bandwidth overhead_.
|
||||
|
||||
The entire protocol has only two source files of ikcp.h, ikcp.c, which can be easily integrated into the user's own protocol stack. You may have implement a P2P, or a UDP-based protocol, but are lack of a set of perfect ARQ reliable protocol implementation, then by simply copying the two files to the existing project, and writing a couple of lines of code, you can use it.
|
||||
KCP is implemented purely as an algorithm; it does not handle sending or receiving packets. It is designed to be transport-agnostic. Users must define their underlying transmission logic (e.g., via UDP) and pass data to KCP through callbacks. Even timekeeping is left to the user; KCP requires the current clock value to be provided externally, making it completely free of internal system calls.
|
||||
|
||||
The protocol consists of two source files: **ikcp.h and ikcp.c**. These files are lightweight and easy to integrate into your existing network stack. Whether you're building a P2P system or a UDP-based protocol that needs a robust ARQ (Automatic Repeat reQuest) mechanism, you can start using KCP by adding these files to your project and writing a few lines of integration code.
|
||||
|
||||
|
||||
# Technical Specifications
|
||||
|
||||
TCP is designed for traffic (the amount of kilobits per second of data that can be transmitted), which focuses on the full use of bandwidth. While KCP is designed for the flow rate (the amount of time it takes to send a single packet from one end to the other), with 10% -20% bandwidth waste in exchange for transmission speed 30%-40% faster than TCP. TCP channel is a grand canal with very slow flow rate, but very large flow per second, while KCP is a small torrent with the rapid flow. KCP has both normal and fast modes, achieving the result of flow rate increase by the following strategies:
|
||||
While TCP is optimized for throughput—maximizing the amount of data transmitted per second (e.g., kilobits/sec)—KCP is designed to focus on latency and packet delivery time. By prioritizing how quickly individual packets travel from sender to receiver, KCP trades 10–20% more bandwidth overhead for 30–40% faster transmission speed compared to TCP.
|
||||
|
||||
Think of TCP as a wide canal: it can carry a large volume of data, but the flow is relatively slow. In contrast, KCP is like a narrow, fast-moving stream—it sends smaller amounts of data more quickly, ensuring lower delay and faster responsiveness.
|
||||
|
||||
KCP supports both normal mode and fast mode, each optimizing performance based on different needs. Its increased flow rate is achieved through several key strategies:
|
||||
|
||||
#### RTO Doubled vs Not Doubled:
|
||||
|
||||
TCP timeout calculation is RTOx2, so three consecutive packet losses will make it RTOx8, which is very terrible, while after KCP fast mode is enabled, it is not x2, but x1.5 (Experimental results show that the value of 1.5 is relatively good), which has improved the transmission speed.
|
||||
In TCP, retransmission timeout (RTO) increases exponentially—each failure doubles the timeout interval (RTO × 2). This means three consecutive losses can escalate to RTO × 8, leading to serious transmission delays.
|
||||
KCP, in contrast, uses a more responsive approach in fast mode: the RTO increases by a factor of 1.5x (based on empirical results), significantly improving recovery speed and reducing delay after packet loss.
|
||||
|
||||
#### Selective Retransmission vs Full Retransmission:
|
||||
|
||||
When packet loss occurs in TCP, all the data after the lost packet will be retransmitted, while KCP is selective retransmission, and only re-transmits the data packets that are really lost.
|
||||
TCP often retransmits all subsequent data after a lost packet, which can lead to excessive redundancy.
|
||||
KCP implements selective retransmission, ensuring that only the actually lost packets are resent, minimizing unnecessary data transmission and improving efficiency.
|
||||
|
||||
#### Fast Retransmission:
|
||||
|
||||
The transmitting terminal sends 1, 2, 3, 4 and 5 packets, and then receives the remote ACK: 1, 3, 4 and 5, when receiving ACK3, KCP knows that 2 is skipped 1 time, and when receiving ACK4, it knows that 2 is skipped 2 times, at this point, it can consider that 2 is lost, without waiting until timeout, it will directly retransmit packet 2, which can greatly improve the transmission speed when packet loss occurs.
|
||||
When the sender transmits packets 1 through 5 and receives ACKs for 1, 3, 4, and 5, KCP deduces from missing ACK2 that packet 2 has likely been lost. After receiving multiple out-of-order ACKs, KCP can immediately trigger a fast retransmit of packet 2—without waiting for a timeout—drastically reducing retransmission latency under packet loss.
|
||||
|
||||
#### Delayed ACK vs Non-delayed ACK:
|
||||
|
||||
In order to make full use of the bandwidth, TCP delays sending an ACK (Even NODELAY does not work), so that the timeout calculation will come out with a relatively high RTT, which has extended the judgment process when packet loss occurs. While for KCP, it is adjustable whether to delay sending an ACK.
|
||||
TCP often delays ACKs to optimize throughput, which can unintentionally inflate RTT calculations and delay loss detection—even with `NODELAY` settings.
|
||||
KCP provides configurable ACK behavior, allowing ACKs to be sent immediately when needed, enhancing responsiveness in latency-sensitive applications.
|
||||
|
||||
#### UNA vs ACK+UNA:
|
||||
|
||||
There are two kinds of ARQ model responses: UNA (All packets before this number received, such as TCP) and ACK (The packet with this number received). Using UNA alone will result in full retransmissions, and using ACK alone has too much cost for packet loss, hence in the previous protocols, one of the two has been selected; while in KCP protocol, all packets have UNA information except for a single ACK packet.
|
||||
ARQ protocols typically use either:
|
||||
|
||||
UNA (Unacknowledged Acknowledgment): Confirms all packets before a given sequence number (e.g., TCP).
|
||||
|
||||
ACK: Confirms receipt of a specific packet.
|
||||
|
||||
Each has tradeoffs: UNA can lead to full retransmissions, and standalone ACKs create overhead during loss.
|
||||
KCP combines both—each control message contains UNA info, and a dedicated ACK frame is used when necessary. This hybrid model increases reliability and precision without excess cost.
|
||||
|
||||
#### Non-concessional Flow Control:
|
||||
|
||||
KCP normal mode uses the same fair concession rules as TCP, i.e., the send window size is determined by: four factors including the size of the send cache, the size of the receive buffer at the receiving end, packet loss concession and slow start. However, when sending small data with high timeliness requirement, it is allowed to select skipping the latter two steps through configuration, and use only the first two items to control the transmission frequency, sacrificing some of the fairness and bandwidth utilization, in exchange for the effect of smooth transmission even when BT is opened.
|
||||
By default, KCP follows TCP's fair flow control—factoring in send buffer size, receiver buffer, congestion control, and slow-start.
|
||||
However, for latency-critical small data, KCP can be configured to bypass congestion and slow-start, relying only on buffer sizes. This allows smooth transmission even under heavy network load (e.g., when BitTorrent is active), sacrificing some fairness for timeliness.
|
||||
|
||||
|
||||
# Quick Install
|
||||
@@ -57,7 +76,7 @@ You can download and install kcp using the [vcpkg](https://github.com/Microsoft/
|
||||
./vcpkg integrate install
|
||||
./vcpkg install kcp
|
||||
|
||||
The kcp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
Microsoft team members and community contributors keep the kcp port in vcpkg up to date. If the version is outdated, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
# Basic Usage
|
||||
|
||||
@@ -103,7 +122,7 @@ The kcp port in vcpkg is kept up to date by Microsoft team members and community
|
||||
ikcp_input(kcp, received_udp_packet, received_udp_size);
|
||||
```
|
||||
|
||||
After processing the output / input of the lower layer protocols, KCP protocol can work normally, and ikcp_send is used to send data to the remote end. While the other end uses ikcp_recv (kcp, ptr, size) to receive the data.
|
||||
After processing the output/input of the lower layer protocols, the KCP protocol can work normally. ikcp_send is used to send data to the remote end, while the other end uses ikcp_recv (kcp, ptr, size) to receive the data.
|
||||
|
||||
|
||||
# Protocol Configuration
|
||||
@@ -115,10 +134,10 @@ The protocol default mode is a standard ARQ, and various acceleration switches c
|
||||
int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc)
|
||||
```
|
||||
|
||||
- `nodelay` : Whether nodelay mode is enabled, 0 is not enabled; 1 enabled.
|
||||
- `interval` :Protocol internal work interval, in milliseconds, such as 10 ms or 20 ms.
|
||||
- `resend` :Fast retransmission mode, 0 represents off by default, 2 can be set (2 ACK spans will result in direct retransmission)
|
||||
- `nc` :Whether to turn off flow control, 0 represents “Do not turn off” by default, 1 represents “Turn off”.
|
||||
- `nodelay`: Whether nodelay mode is enabled, 0 is not enabled; 1 enabled.
|
||||
- `interval` :P rotocol internal work interval, in milliseconds, such as 10 ms or 20 ms.
|
||||
- `resend` :Fast retransmission mode, 0 represents off by default, 2 can be set (2 ACK spans will result in direct retransmission)
|
||||
- `nc` : Whether to turn off flow control, 0 represents “Do not turn off” by default, 1 represents “Turn off”.
|
||||
- Normal Mode: ikcp_nodelay(kcp, 0, 40, 0, 0);
|
||||
- Turbo Mode: ikcp_nodelay(kcp, 1, 10, 2, 1);
|
||||
|
||||
@@ -126,11 +145,11 @@ The protocol default mode is a standard ARQ, and various acceleration switches c
|
||||
```cpp
|
||||
int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd);
|
||||
```
|
||||
The call will set the maximum send window and maximum receive window size of the procotol, which is 32 by default. This can be understood as SND_BUF and RCV_BUF of TCP, but the unit is not the same, SND / RCV_BUF unit is byte, while this unit is the packet.
|
||||
By default, the call will set the maximum send window and maximum receive window size of the procotol, 32. This can be understood as SND_BUF and RCV_BUF of TCP, but the unit is not the same, SND / RCV_BUF unit is byte, while this unit is the packet.
|
||||
|
||||
3. Maximum Transmission Unit:
|
||||
|
||||
Pure algorithm protocol is not responsible for MTU detection, the default mtu is 1400 bytes, which can be set using ikcp_setmtu. The value will affect the maximum transmission unit upon data packet merging and fragmentation.
|
||||
The algorithm protocol is not responsible for MTU detection. The default MTU is 1400 bytes, which can be set using ikcp_setmtu. The value will affect the maximum transmission unit upon data packet merging and fragmentation.
|
||||
|
||||
4. Minimum RTO:
|
||||
|
||||
@@ -143,7 +162,7 @@ The protocol default mode is a standard ARQ, and various acceleration switches c
|
||||
|
||||
# Document Indexing
|
||||
|
||||
Both the use and configuration of the protocol is very simple, in most cases, after you read the above contents, basically you will be able to use it. If you need further fine control, such as changing the KCP memory allocator, or if you need more efficient large-scale scheduling of KCP links (such as more than 3,500 links), or to better combine with TCP, you can continue the extensive reading:
|
||||
Both the use and configuration of the protocol is straightforward, in most cases, after you read the above contents, you can use it. If you need further fine control, such as changing the KCP memory allocator, or if you need more efficient large-scale scheduling of KCP links (such as more than 3,500 links), or to better combine with TCP, you can continue the extensive reading:
|
||||
|
||||
- [KCP Best Practice](https://github.com/skywind3000/kcp/wiki/KCP-Best-Practice-EN)
|
||||
- [Integration with the Existing TCP Server](https://github.com/skywind3000/kcp/wiki/KCP-Best-Practice-EN)
|
||||
@@ -158,19 +177,31 @@ Both the use and configuration of the protocol is very simple, in most cases, af
|
||||
- [HP-Socket](https://github.com/ldcsaa/HP-Socket): High Performance TCP/UDP/HTTP Communication Component.
|
||||
- [frp](https://github.com/fatedier/frp): A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.
|
||||
- [asio-kcp](https://github.com/libinzhangyuan/asio_kcp): Use the complete UDP network library of KCP, complete implementation of UDP-based link state management, session control and KCP protocol scheduling, etc.
|
||||
- [kcp-cpp](https://github.com/Unit-X/kcp-cpp): Multi-platform (Windows, MacOS, Linux) C++ implementation of KCP as a simple library in your application. Contains socket handling and helper functions for all platforms.
|
||||
- [kcp-perl](https://github.com/Homqyy/kcp-perl): Perl extensions for kcp. It's OOP and Perl-Like.
|
||||
- [kcp-java](https://github.com/hkspirt/kcp-java):Implementation of Java version of KCP protocol.
|
||||
- [kcp-netty](https://github.com/szhnet/kcp-netty):Java implementation of KCP based on Netty.
|
||||
- [java-kcp](https://github.com/l42111996/java-Kcp): JAVA version KCP, based on netty implementation (including fec function)
|
||||
- [csharp-kcp](https://github.com/l42111996/csharp-kcp): csharp version KCP, based on dotNetty implementation (including fec function)
|
||||
- [kcp-go](https://github.com/xtaci/kcp-go): High-security GO language implementation of kcp, including simple implementation of UDP session management, as a base library for subsequent development.
|
||||
- [kcp-csharp](https://github.com/limpo1989/kcp-csharp): The csharp migration of kcp, containing the session management, which can access the above kcp-go server.
|
||||
- [KcpTransport](https://github.com/Cysharp/KcpTransport): KcpTransport is built on top of KCP ported to Pure C#, with implementations of Syn Cookie handshake, connection management, Unreliable communication, and KeepAlive. In the future, encryption will also be supported.
|
||||
- [Kcp-CSharp](https://github.com/Molth/Kcp-CSharp): a pure C# KCP instance callback(delegate) wrapper for (Unity/Godot/.NET)
|
||||
- [kcp2k](https://github.com/vis2k/kcp2k/): Line-by-line translation to C#, with optional Server/Client on top.
|
||||
- [kcp-rs](https://github.com/en/kcp-rs): The rust migration of KCP
|
||||
- [kcp-rust-native](https://github.com/b23r0/kcp-rust-native):KCP bindings for Rust
|
||||
- [lua-kcp](https://github.com/linxiaolong/lua-kcp): Lua extension of KCP, applicable for Lua server
|
||||
- [node-kcp](https://github.com/leenjewel/node-kcp): KCP interface for node-js
|
||||
- [nysocks](https://github.com/oyyd/nysocks): Nysocks provides proxy services base on libuv and kcp for nodejs users. Both SOCKS5 and ss protocols are supported in the client.
|
||||
- [shadowsocks-android](https://github.com/shadowsocks/shadowsocks-android): Shadowsocks for android has integrated kcptun using kcp protocol to accelerate shadowsocks, with good results
|
||||
- [kcpuv](https://github.com/elisaday/kcpuv): The kcpuv library developed with libuv, currently still in the early alpha phase.
|
||||
- [xkcptun](https://github.com/liudf0716/xkcptun): C language implementation of kcptun, embedded-friendly for [LEDE](https://github.com/lede-project/source) and [OpenWrt](https://github.com/openwrt/openwrt) projects.
|
||||
|
||||
- [yasio](https://github.com/yasio/yasio): A cross-platform asynchronous socket library focus on any client application with kcp support, easy to use, API same with UDP and TCP, see [benchmark-pump](https://github.com/yasio/yasio/blob/master/benchmark.md).
|
||||
- [gouxp](https://github.com/shaoyuan1943/gouxp): Implementing a callback-based KCP development package with Go, with decryption and FEC support, is easy to use.
|
||||
- [kcp.py](https://github.com/RealistikDash/kcp.py): Python bindings and networking with an emphasis on dev friendliness.
|
||||
- [pykcp](https://github.com/enkiller/pykcp): KCP implementation for Python version.
|
||||
- [php-ext-kcp](https://github.com/wpjscc/php-ext-kcp): php extension for KCP.
|
||||
- [asio-kcp(new)](https://github.com/sniper00/asio-kcp): KCP implementation for C++/Asio, with Modern C++/Asio async features, such as coroutine.
|
||||
|
||||
# Protocol Comparison
|
||||
|
||||
@@ -192,7 +223,7 @@ For specifics please refer to: [Reliable Udp Benchmark](https://github.com/libin
|
||||
|
||||
MMO Engine [SpatialOS](https://improbable.io/spatialOS) has a benchmark report on KCP/TCP/RakNet:
|
||||
|
||||

|
||||

|
||||
|
||||
for more details, please see the report itself:
|
||||
|
||||
|
||||
48
README.md
48
README.md
@@ -1,21 +1,24 @@
|
||||
KCP - A Fast and Reliable ARQ Protocol
|
||||
======================================
|
||||
|
||||
[![Powered][2]][1] [![Build Status][4]][5]
|
||||
[![Powered][3]][1]
|
||||
[![GitHub license][6]][7]
|
||||
[](#backers)
|
||||
[](#sponsors)
|
||||
[](#sponsors)
|
||||
|
||||
[1]: https://github.com/skywind3000/kcp
|
||||
[2]: http://skywind3000.github.io/word/images/kcp.svg
|
||||
[3]: https://raw.githubusercontent.com/skywind3000/kcp/master/kcp.svg
|
||||
[2]: https://github.com/skywind3000/kcp/raw/master/kcp.svg
|
||||
[3]: https://github.com/skywind3000/kcp/raw/master/kcp.svg
|
||||
[4]: https://api.travis-ci.org/skywind3000/kcp.svg?branch=master
|
||||
[5]: https://travis-ci.org/skywind3000/kcp
|
||||
[6]: https://img.shields.io/badge/license-MIT-blue.svg
|
||||
[7]: https://github.com/skywind3000/kcp/blob/master/LICENSE
|
||||
|
||||
[README in English](https://github.com/skywind3000/kcp/blob/master/README.en.md)
|
||||
|
||||
# 简介
|
||||
|
||||
KCP是一个快速可靠协议,能以比 TCP浪费10%-20%的带宽的代价,换取平均延迟降低 30%-40%,且最大延迟降低三倍的传输效果。纯算法实现,并不负责底层协议(如UDP)的收发,需要使用者自己定义下层数据包的发送方式,以 callback的方式提供给 KCP。 连时钟都需要外部传递进来,内部不会有任何一次系统调用。
|
||||
KCP是一个快速可靠协议,能以比 TCP 浪费 10%-20% 的带宽的代价,换取平均延迟降低 30%-40%,且最大延迟降低三倍的传输效果。纯算法实现,并不负责底层协议(如UDP)的收发,需要使用者自己定义下层数据包的发送方式,以 callback的方式提供给 KCP。 连时钟都需要外部传递进来,内部不会有任何一次系统调用。
|
||||
|
||||
整个协议只有 ikcp.h, ikcp.c两个源文件,可以方便的集成到用户自己的协议栈中。也许你实现了一个P2P,或者某个基于 UDP的协议,而缺乏一套完善的ARQ可靠协议实现,那么简单的拷贝这两个文件到现有项目中,稍微编写两行代码,即可使用。
|
||||
|
||||
@@ -160,12 +163,19 @@ vcpkg中的kcp库由Microsoft团队成员和社区贡献者保持最新状态。
|
||||
- [kcp-java](https://github.com/hkspirt/kcp-java): Java版本 KCP协议实现。
|
||||
- [kcp-netty](https://github.com/szhnet/kcp-netty): kcp的Java语言实现,基于netty。
|
||||
- [java-kcp](https://github.com/l42111996/java-Kcp): JAVA版本KCP,基于netty实现(包含fec功能)
|
||||
- [csharp-kcp](https://github.com/l42111996/csharp-kcp): csharp版本KCP,基于dotNetty实现(包含fec功能)
|
||||
- [kcp-cpp](https://github.com/Unit-X/kcp-cpp): KCP 的多平台(Windows、MacOS、Linux)C++ 实现作为应用程序中的简单库。包含适用于所有平台的套接字处理和辅助函数。
|
||||
- [kcp-perl](https://github.com/Homqyy/kcp-perl): kcp的Perl实现,其是面向对象的,Perl-Like的。
|
||||
- [kcp-go](https://github.com/xtaci/kcp-go): 高安全性的kcp的 GO语言实现,包含 UDP会话管理的简单实现,可以作为后续开发的基础库。
|
||||
- [kcp-csharp](https://github.com/limpo1989/kcp-csharp): kcp的 csharp移植,同时包含一份回话管理,可以连接上面kcp-go的服务端。
|
||||
- [kcp-csharp](https://github.com/KumoKyaku/KCP): 新版本 Kcp的 csharp移植。线程安全,运行时无alloc,对gc无压力。
|
||||
- [KcpTransport](https://github.com/Cysharp/KcpTransport): kcp的csharp移植,实现了 Syn Cookie 握手、连接管理、不可靠通信、KeepAlive,未来还将支持加密。
|
||||
- [Kcp-CSharp](https://github.com/Molth/Kcp-CSharp): kcp的csharp移植,非托管包装器。
|
||||
- [kcp2k](https://github.com/vis2k/kcp2k/): Line-by-line translation to C#, with optional Server/Client on top.
|
||||
- [kcp-rs](https://github.com/en/kcp-rs): KCP的 rust移植
|
||||
- [kcp-rust](https://github.com/Matrix-Zhang/kcp):新版本 KCP的 rust 移植
|
||||
- [tokio-kcp](https://github.com/Matrix-Zhang/tokio_kcp):rust tokio 的 kcp 集成
|
||||
- [kcp-rust-native](https://github.com/b23r0/kcp-rust-native):rust 的 kcp bindings
|
||||
- [lua-kcp](https://github.com/linxiaolong/lua-kcp): KCP的 Lua扩展,用于 Lua服务器
|
||||
- [node-kcp](https://github.com/leenjewel/node-kcp): node-js 的 KCP 接口
|
||||
- [nysocks](https://github.com/oyyd/nysocks): 基于libuv实现的[node-addon](https://nodejs.org/api/addons.html),提供nodejs版本的代理服务,客户端接入支持SOCKS5和ss两种协议
|
||||
@@ -175,15 +185,29 @@ vcpkg中的kcp库由Microsoft团队成员和社区贡献者保持最新状态。
|
||||
- [rpcx](https://github.com/smallnest/rpcx) :RPC 框架,1000+ 星,使用 kcpgo 加速 RPC
|
||||
- [xkcptun](https://github.com/liudf0716/xkcptun): c语言实现的kcptun,主要用于[OpenWrt](https://github.com/openwrt/openwrt), [LEDE](https://github.com/lede-project/source)开发的路由器项目上
|
||||
- [et-frame](https://github.com/egametang/ET): C#前后端框架(前端unity3d),统一用C#开发游戏,实现了前后端kcp协议
|
||||
- [yasio](https://github.com/yasio/yasio): 一个跨平台专注于任意客户端程序的异步socket库, 易于使用,相同的API操作KCP/TCP/UDP, 性能测试结果: [benchmark-pump](https://github.com/yasio/yasio/blob/master/benchmark.md).
|
||||
- [gouxp](https://github.com/shaoyuan1943/gouxp): 用Go实现基于回调方式的KCP开发包,包含加解密和FEC支持,简单易用。
|
||||
- [skcp](https://github.com/xboss/skcp): 基于libev实现的库,具备传输加密及基本的连接管理能力。
|
||||
- [pykcp](https://github.com/enkiller/pykcp): Python 版本的 KCP 实现
|
||||
- [php-ext-kcp](https://github.com/wpjscc/php-ext-kcp): php 的 KCP 扩展
|
||||
- [asio-kcp(new)](https://github.com/sniper00/asio-kcp): c++的asio/kcp支持,支持asio协程等现代c++异步模型
|
||||
|
||||
# 商业案例
|
||||
|
||||
- [明日帝国](https://www.taptap.com/app/50664):Game K17 的 《明日帝国》 (Google Play),使用 KCP 加速游戏消息,让全球玩家流畅联网
|
||||
- [仙灵大作战](https://www.taptap.com/app/27242):4399 的 MOBA游戏,使用 KCP 优化游戏同步
|
||||
- [原神](https://ys.mihoyo.com/):米哈游的《原神》使用 KCP 降低游戏消息的传输耗时,提升操作的体验。
|
||||
- [SpatialOS](https://improbable.io/spatialOS): 大型多人分布式游戏服务端引擎,BigWorld 的后继者,使用 KCP 加速数据传输。
|
||||
- [西山居](https://www.xishanju.com/):使用 KCP 进行游戏数据加速。
|
||||
- [CC](http://cc.163.com/):网易 CC 使用 kcp 加速视频推流,有效提高流畅性
|
||||
- [BOBO](http://bobo.163.com/):网易 BOBO 使用 kcp 加速主播推流
|
||||
- [云帆加速](http://www.yfcloud.com/):使用 KCP 加速文件传输和视频推流,优化了台湾主播推流的流畅度
|
||||
- [SpatialOS](https://improbable.io/spatialOS): 大型多人分布式游戏服务端引擎,BigWorld 的后继者,使用 KCP 加速数据传输。
|
||||
- [UU](https://uu.163.com):网易 UU 加速器使用 KCP/KCPTUN 经行远程传输加速。
|
||||
- [阿里云](https://cn.aliyun.com/):阿里云的视频传输加速服务 GRTN 使用 KCP 进行音视频数据传输优化,动态加速产品也使用 KCP。
|
||||
- [云帆加速](http://www.yfcloud.com/):使用 KCP 加速文件传输和视频推流,优化了台湾主播推流的流畅度。
|
||||
- [明日帝国](https://www.taptap.com/app/50664):Game K17 的 《明日帝国》 (Google Play),使用 KCP 加速游戏消息,让全球玩家流畅联网
|
||||
- [仙灵大作战](https://www.taptap.com/app/27242):4399 的 MOBA游戏,使用 KCP 优化游戏同步
|
||||
|
||||
相关阅读:[《原神》也在使用 KCP 加速游戏消息](https://skywind.me/blog/archives/2706)
|
||||
|
||||
KCP 成功的运行在多个用户规模上亿的项目上,为他们提供了更加灵敏和丝滑网络体验。
|
||||
|
||||
欢迎告知更多案例
|
||||
|
||||
@@ -207,7 +231,7 @@ vcpkg中的kcp库由Microsoft团队成员和社区贡献者保持最新状态。
|
||||
|
||||
大型多人游戏服务端引擎 [SpatialOS](https://improbable.io/spatialOS) 在集成 KCP 协议后做了同 TCP/RakNet 的评测:
|
||||
|
||||

|
||||

|
||||
|
||||
对比了在服务端刷新率为 60 Hz 同时维护 50 个角色时的响应时间,详细对比报告见:
|
||||
|
||||
@@ -229,11 +253,11 @@ For more information, please see the [Success Stories](https://github.com/skywin
|
||||
|
||||
作者:林伟 (skywind3000)
|
||||
|
||||
欢迎关注我的:[twitter](https://twitter.com/skywind3000) 和 [zhihu](https://www.zhihu.com/people/skywind3000)。
|
||||
欢迎关注我的:[个人博客](https://skywind.me/blog) 和 [推特](https://x.com/skywind3000)。
|
||||
|
||||
我在多年的开发经历中,一直都喜欢研究解决程序中的一些瓶颈问题,早年喜欢游戏开发,照着《VGA编程》来做游戏图形,读 Michael Abrash 的《图形程序开发人员指南》做软渲染器,爱好摆弄一些能够榨干 CPU 能够运行更快的代码,参加工作后,兴趣转移到服务端和网络相关的技术。
|
||||
|
||||
2007 年时做了几个传统游戏后开始研究快速动作游戏的同步问题,期间写过不少文章,算是国内比较早研究同步问题的人,然而发现不管怎么解决同步都需要在网络传输方面有所突破,后来离开游戏转行互联网后也发现不少领域有这方面的需求,于是开始花时间在网络传输这个领域上,尝试基于 UDP 实现一些保守的可靠协议,反照 BSD Lite 4.4 的代码实现一些类 TCP 协议,觉得比较有意思,又接着实现一些 P2P 和动态路由网相关的玩具。KCP 协议诞生于 2011 年,基本算是自己传输方面做的几个玩具中的一个。
|
||||
2007 年时做了几个传统游戏后开始研究快速动作游戏的同步问题,期间写过不少文章,算是国内比较早研究同步问题的人,然而发现不管怎么解决同步都需要在网络传输方面有所突破,后来离开游戏转行互联网后也发现不少领域有这方面的需求,于是开始花时间在网络传输这个领域上,尝试基于 UDP 实现一些保守的可靠协议,仿照 BSD Lite 4.4 的代码实现一些类 TCP 协议,觉得比较有意思,又接着实现一些 P2P 和动态路由网相关的玩具。KCP 协议诞生于 2011 年,基本算是自己传输方面做的几个玩具中的一个。
|
||||
|
||||
Kcptun 的作者 xtaci 是我的大学同学,我俩都是学通信的,经常在一起研究如何进行传输优化。
|
||||
|
||||
|
||||
35
ikcp.c
35
ikcp.c
@@ -17,7 +17,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define IKCP_FASTACK_CONSERVE
|
||||
|
||||
//=====================================================================
|
||||
// KCP BASIC
|
||||
@@ -71,7 +71,7 @@ static inline char *ikcp_encode16u(char *p, unsigned short w)
|
||||
*(unsigned char*)(p + 0) = (w & 255);
|
||||
*(unsigned char*)(p + 1) = (w >> 8);
|
||||
#else
|
||||
*(unsigned short*)(p) = w;
|
||||
memcpy(p, &w, 2);
|
||||
#endif
|
||||
p += 2;
|
||||
return p;
|
||||
@@ -84,7 +84,7 @@ static inline const char *ikcp_decode16u(const char *p, unsigned short *w)
|
||||
*w = *(const unsigned char*)(p + 1);
|
||||
*w = *(const unsigned char*)(p + 0) + (*w << 8);
|
||||
#else
|
||||
*w = *(const unsigned short*)p;
|
||||
memcpy(w, p, 2);
|
||||
#endif
|
||||
p += 2;
|
||||
return p;
|
||||
@@ -99,7 +99,7 @@ static inline char *ikcp_encode32u(char *p, IUINT32 l)
|
||||
*(unsigned char*)(p + 2) = (unsigned char)((l >> 16) & 0xff);
|
||||
*(unsigned char*)(p + 3) = (unsigned char)((l >> 24) & 0xff);
|
||||
#else
|
||||
*(IUINT32*)p = l;
|
||||
memcpy(p, &l, 4);
|
||||
#endif
|
||||
p += 4;
|
||||
return p;
|
||||
@@ -114,7 +114,7 @@ static inline const char *ikcp_decode32u(const char *p, IUINT32 *l)
|
||||
*l = *(const unsigned char*)(p + 1) + (*l << 8);
|
||||
*l = *(const unsigned char*)(p + 0) + (*l << 8);
|
||||
#else
|
||||
*l = *(const IUINT32*)p;
|
||||
memcpy(l, p, 4);
|
||||
#endif
|
||||
p += 4;
|
||||
return p;
|
||||
@@ -470,6 +470,7 @@ int ikcp_send(ikcpcb *kcp, const char *buffer, int len)
|
||||
{
|
||||
IKCPSEG *seg;
|
||||
int count, i;
|
||||
int sent = 0;
|
||||
|
||||
assert(kcp->mss > 0);
|
||||
if (len < 0) return -1;
|
||||
@@ -497,17 +498,22 @@ int ikcp_send(ikcpcb *kcp, const char *buffer, int len)
|
||||
len -= extend;
|
||||
iqueue_del_init(&old->node);
|
||||
ikcp_segment_delete(kcp, old);
|
||||
sent = extend;
|
||||
}
|
||||
}
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
return sent;
|
||||
}
|
||||
}
|
||||
|
||||
if (len <= (int)kcp->mss) count = 1;
|
||||
else count = (len + kcp->mss - 1) / kcp->mss;
|
||||
|
||||
if (count >= (int)IKCP_WND_RCV) return -2;
|
||||
if (count >= (int)IKCP_WND_RCV) {
|
||||
if (kcp->stream != 0 && sent > 0)
|
||||
return sent;
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (count == 0) count = 1;
|
||||
|
||||
@@ -531,9 +537,10 @@ int ikcp_send(ikcpcb *kcp, const char *buffer, int len)
|
||||
buffer += size;
|
||||
}
|
||||
len -= size;
|
||||
sent += size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return sent;
|
||||
}
|
||||
|
||||
|
||||
@@ -636,12 +643,12 @@ static void ikcp_parse_fastack(ikcpcb *kcp, IUINT32 sn, IUINT32 ts)
|
||||
//---------------------------------------------------------------------
|
||||
static void ikcp_ack_push(ikcpcb *kcp, IUINT32 sn, IUINT32 ts)
|
||||
{
|
||||
size_t newsize = kcp->ackcount + 1;
|
||||
IUINT32 newsize = kcp->ackcount + 1;
|
||||
IUINT32 *ptr;
|
||||
|
||||
if (newsize > kcp->ackblock) {
|
||||
IUINT32 *acklist;
|
||||
size_t newblock;
|
||||
IUINT32 newblock;
|
||||
|
||||
for (newblock = 8; newblock < newsize; newblock <<= 1);
|
||||
acklist = (IUINT32*)ikcp_malloc(newblock * sizeof(IUINT32) * 2);
|
||||
@@ -652,7 +659,7 @@ static void ikcp_ack_push(ikcpcb *kcp, IUINT32 sn, IUINT32 ts)
|
||||
}
|
||||
|
||||
if (kcp->acklist != NULL) {
|
||||
size_t x;
|
||||
IUINT32 x;
|
||||
for (x = 0; x < kcp->ackcount; x++) {
|
||||
acklist[x * 2 + 0] = kcp->acklist[x * 2 + 0];
|
||||
acklist[x * 2 + 1] = kcp->acklist[x * 2 + 1];
|
||||
@@ -1060,9 +1067,11 @@ void ikcp_flush(ikcpcb *kcp)
|
||||
segment->xmit++;
|
||||
kcp->xmit++;
|
||||
if (kcp->nodelay == 0) {
|
||||
segment->rto += kcp->rx_rto;
|
||||
segment->rto += _imax_(segment->rto, (IUINT32)kcp->rx_rto);
|
||||
} else {
|
||||
segment->rto += kcp->rx_rto / 2;
|
||||
IINT32 step = (kcp->nodelay < 2)?
|
||||
((IINT32)(segment->rto)) : kcp->rx_rto;
|
||||
segment->rto += step / 2;
|
||||
}
|
||||
segment->resendts = current + segment->rto;
|
||||
lost = 1;
|
||||
|
||||
5
test.cpp
5
test.cpp
@@ -70,8 +70,8 @@ void test(int mode)
|
||||
// 第三个参数 interval为内部处理时钟,默认设置为 10ms
|
||||
// 第四个参数 resend为快速重传指标,设置为2
|
||||
// 第五个参数 为是否禁用常规流控,这里禁止
|
||||
ikcp_nodelay(kcp1, 1, 10, 2, 1);
|
||||
ikcp_nodelay(kcp2, 1, 10, 2, 1);
|
||||
ikcp_nodelay(kcp1, 2, 10, 2, 1);
|
||||
ikcp_nodelay(kcp2, 2, 10, 2, 1);
|
||||
kcp1->rx_minrto = 10;
|
||||
kcp1->fastresend = 1;
|
||||
}
|
||||
@@ -178,3 +178,4 @@ fast mode result (20207ms):
|
||||
avgrtt=138 maxrtt=392
|
||||
*/
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user