mirror of
https://github.com/skywind3000/kcp.git
synced 2025-03-14 09:00:06 +08:00
Merge branch 'master' of https://github.com/skywind3000/kcp
This commit is contained in:
commit
234239b9e2
11
README.en.md
11
README.en.md
@ -147,6 +147,7 @@ Both the use and configuration of the protocol is very simple, in most cases, af
|
||||
- [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-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)
|
||||
- [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.
|
||||
- [kcp-rs](https://github.com/en/kcp-rs): The rust migration of KCP
|
||||
@ -176,13 +177,21 @@ Thanks to [zhangyuan](https://github.com/libinzhangyuan) the author of [asio-kcp
|
||||
|
||||
For specifics please refer to: [Reliable Udp Benchmark](https://github.com/libinzhangyuan/reliable_udp_bench_mark) and [KCP-Benchmark](https://github.com/skywind3000/kcp/wiki/KCP-Benchmark), for more guidance to the hesitant users.
|
||||
|
||||
MMO Engine [SpatialOS](https://improbable.io/spatialOS) has a benchmark report on KCP/TCP/RakNet:
|
||||
|
||||

|
||||
|
||||
for more details, please see the report itself:
|
||||
|
||||
- [Kcp a new low latency secure network stack](https://improbable.io/blog/kcp-a-new-low-latency-secure-network-stack)
|
||||
|
||||
# KCP is used by
|
||||
|
||||
See [Success Stories](https://github.com/skywind3000/kcp/wiki/Success-Stories).
|
||||
|
||||
# Donation
|
||||
|
||||

|
||||

|
||||
|
||||
Donation is welcome by using alipay, the money will be used to improve the protocol and documentation.
|
||||
|
||||
|
17
README.md
17
README.md
@ -1,8 +1,8 @@
|
||||
KCP - A Fast and Reliable ARQ Protocol
|
||||
======================================
|
||||
|
||||
[![Powered][2]][1] [![Build Status][4]][5]
|
||||
[](#backers)
|
||||
[![Powered][2]][1] [![Build Status][4]][5]
|
||||
[](#backers)
|
||||
[](#sponsors)
|
||||
|
||||
[1]: https://github.com/skywind3000/kcp
|
||||
@ -146,6 +146,7 @@ TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的
|
||||
- [asio-kcp](https://github.com/libinzhangyuan/asio_kcp): 使用 KCP的完整 UDP网络库,完整实现了基于 UDP的链接状态管理,会话控制,KCP协议调度等
|
||||
- [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功能)
|
||||
- [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无压力。
|
||||
@ -169,6 +170,7 @@ TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的
|
||||
- [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 加速数据传输。
|
||||
|
||||
欢迎告知更多案例
|
||||
|
||||
@ -190,12 +192,21 @@ TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的
|
||||
|
||||
具体见:[横向比较](https://github.com/libinzhangyuan/reliable_udp_bench_mark) 和 [评测数据](https://github.com/skywind3000/kcp/wiki/KCP-Benchmark),为犹豫选择的人提供了更多指引。
|
||||
|
||||
大型多人游戏服务端引擎 [SpatialOS](https://improbable.io/spatialOS) 在集成 KCP 协议后做了同 TCP/RakNet 的评测:
|
||||
|
||||

|
||||
|
||||
对比了在服务端刷新率为 60 Hz 同时维护 50 个角色时的响应时间,详细对比报告见:
|
||||
|
||||
- [Kcp a new low latency secure network stack](https://improbable.io/blog/kcp-a-new-low-latency-secure-network-stack)
|
||||
|
||||
# 项目历史
|
||||
|
||||
See [Success Stories](https://github.com/skywind3000/kcp/wiki/Success-Stories).
|
||||
|
||||
# 欢迎捐赠
|
||||
|
||||

|
||||

|
||||
|
||||
欢迎使用支付宝手扫描上面的二维码,对该项目进行捐赠。捐赠款项将用于持续优化 KCP协议以及完善文档。
|
||||
|
||||
|
47
ikcp.c
47
ikcp.c
@ -43,6 +43,7 @@ const IUINT32 IKCP_THRESH_INIT = 2;
|
||||
const IUINT32 IKCP_THRESH_MIN = 2;
|
||||
const IUINT32 IKCP_PROBE_INIT = 7000; // 7 secs to probe window size
|
||||
const IUINT32 IKCP_PROBE_LIMIT = 120000; // up to 120 secs to probe window
|
||||
const IUINT32 IKCP_FASTACK_LIMIT = 5; // max times to trigger fastack
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
@ -66,7 +67,7 @@ static inline const char *ikcp_decode8u(const char *p, unsigned char *c)
|
||||
/* encode 16 bits unsigned int (lsb) */
|
||||
static inline char *ikcp_encode16u(char *p, unsigned short w)
|
||||
{
|
||||
#if IWORDS_BIG_ENDIAN
|
||||
#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN
|
||||
*(unsigned char*)(p + 0) = (w & 255);
|
||||
*(unsigned char*)(p + 1) = (w >> 8);
|
||||
#else
|
||||
@ -79,7 +80,7 @@ static inline char *ikcp_encode16u(char *p, unsigned short w)
|
||||
/* decode 16 bits unsigned int (lsb) */
|
||||
static inline const char *ikcp_decode16u(const char *p, unsigned short *w)
|
||||
{
|
||||
#if IWORDS_BIG_ENDIAN
|
||||
#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN
|
||||
*w = *(const unsigned char*)(p + 1);
|
||||
*w = *(const unsigned char*)(p + 0) + (*w << 8);
|
||||
#else
|
||||
@ -92,7 +93,7 @@ static inline const char *ikcp_decode16u(const char *p, unsigned short *w)
|
||||
/* encode 32 bits unsigned int (lsb) */
|
||||
static inline char *ikcp_encode32u(char *p, IUINT32 l)
|
||||
{
|
||||
#if IWORDS_BIG_ENDIAN
|
||||
#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN
|
||||
*(unsigned char*)(p + 0) = (unsigned char)((l >> 0) & 0xff);
|
||||
*(unsigned char*)(p + 1) = (unsigned char)((l >> 8) & 0xff);
|
||||
*(unsigned char*)(p + 2) = (unsigned char)((l >> 16) & 0xff);
|
||||
@ -107,7 +108,7 @@ static inline char *ikcp_encode32u(char *p, IUINT32 l)
|
||||
/* decode 32 bits unsigned int (lsb) */
|
||||
static inline const char *ikcp_decode32u(const char *p, IUINT32 *l)
|
||||
{
|
||||
#if IWORDS_BIG_ENDIAN
|
||||
#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN
|
||||
*l = *(const unsigned char*)(p + 3);
|
||||
*l = *(const unsigned char*)(p + 2) + (*l << 8);
|
||||
*l = *(const unsigned char*)(p + 1) + (*l << 8);
|
||||
@ -283,6 +284,7 @@ ikcpcb* ikcp_create(IUINT32 conv, void *user)
|
||||
kcp->logmask = 0;
|
||||
kcp->ssthresh = IKCP_THRESH_INIT;
|
||||
kcp->fastresend = 0;
|
||||
kcp->fastlimit = IKCP_FASTACK_LIMIT;
|
||||
kcp->nocwnd = 0;
|
||||
kcp->xmit = 0;
|
||||
kcp->dead_link = IKCP_DEADLINK;
|
||||
@ -604,7 +606,7 @@ static void ikcp_parse_una(ikcpcb *kcp, IUINT32 una)
|
||||
}
|
||||
}
|
||||
|
||||
static void ikcp_parse_fastack(ikcpcb *kcp, IUINT32 sn)
|
||||
static void ikcp_parse_fastack(ikcpcb *kcp, IUINT32 sn, IUINT32 ts)
|
||||
{
|
||||
struct IQUEUEHEAD *p, *next;
|
||||
|
||||
@ -618,7 +620,12 @@ static void ikcp_parse_fastack(ikcpcb *kcp, IUINT32 sn)
|
||||
break;
|
||||
}
|
||||
else if (sn != seg->sn) {
|
||||
#ifndef IKCP_FASTACK_CONSERVE
|
||||
seg->fastack++;
|
||||
#else
|
||||
if (_itimediff(ts, seg->ts) >= 0)
|
||||
seg->fastack++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -741,8 +748,8 @@ void ikcp_parse_data(ikcpcb *kcp, IKCPSEG *newseg)
|
||||
//---------------------------------------------------------------------
|
||||
int ikcp_input(ikcpcb *kcp, const char *data, long size)
|
||||
{
|
||||
IUINT32 una = kcp->snd_una;
|
||||
IUINT32 maxack = 0;
|
||||
IUINT32 prev_una = kcp->snd_una;
|
||||
IUINT32 maxack = 0, latest_ts = 0;
|
||||
int flag = 0;
|
||||
|
||||
if (ikcp_canlog(kcp, IKCP_LOG_INPUT)) {
|
||||
@ -791,9 +798,18 @@ int ikcp_input(ikcpcb *kcp, const char *data, long size)
|
||||
if (flag == 0) {
|
||||
flag = 1;
|
||||
maxack = sn;
|
||||
latest_ts = ts;
|
||||
} else {
|
||||
if (_itimediff(sn, maxack) > 0) {
|
||||
#ifndef IKCP_FASTACK_CONSERVE
|
||||
maxack = sn;
|
||||
latest_ts = ts;
|
||||
#else
|
||||
if (_itimediff(ts, latest_ts) > 0) {
|
||||
maxack = sn;
|
||||
latest_ts = ts;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (ikcp_canlog(kcp, IKCP_LOG_IN_ACK)) {
|
||||
@ -853,10 +869,10 @@ int ikcp_input(ikcpcb *kcp, const char *data, long size)
|
||||
}
|
||||
|
||||
if (flag != 0) {
|
||||
ikcp_parse_fastack(kcp, maxack);
|
||||
ikcp_parse_fastack(kcp, maxack, latest_ts);
|
||||
}
|
||||
|
||||
if (_itimediff(kcp->snd_una, una) > 0) {
|
||||
if (_itimediff(kcp->snd_una, prev_una) > 0) {
|
||||
if (kcp->cwnd < kcp->rmt_wnd) {
|
||||
IUINT32 mss = kcp->mss;
|
||||
if (kcp->cwnd < kcp->ssthresh) {
|
||||
@ -1048,11 +1064,14 @@ void ikcp_flush(ikcpcb *kcp)
|
||||
lost = 1;
|
||||
}
|
||||
else if (segment->fastack >= resent) {
|
||||
needsend = 1;
|
||||
segment->xmit++;
|
||||
segment->fastack = 0;
|
||||
segment->resendts = current + segment->rto;
|
||||
change++;
|
||||
if ((int)segment->xmit <= kcp->fastlimit ||
|
||||
kcp->fastlimit <= 0) {
|
||||
needsend = 1;
|
||||
segment->xmit++;
|
||||
segment->fastack = 0;
|
||||
segment->resendts = current + segment->rto;
|
||||
change++;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsend) {
|
||||
|
14
ikcp.h
14
ikcp.h
@ -225,7 +225,7 @@ typedef struct IQUEUEHEAD iqueue_head;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// WORD ORDER
|
||||
// BYTE ORDER & ALIGNMENT
|
||||
//---------------------------------------------------------------------
|
||||
#ifndef IWORDS_BIG_ENDIAN
|
||||
#ifdef _BIG_ENDIAN_
|
||||
@ -248,6 +248,17 @@ typedef struct IQUEUEHEAD iqueue_head;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef IWORDS_MUST_ALIGN
|
||||
#if defined(__i386__) || defined(__i386) || defined(_i386_)
|
||||
#define IWORDS_MUST_ALIGN 0
|
||||
#elif defined(_M_IX86) || defined(_X86_) || defined(__x86_64__)
|
||||
#define IWORDS_MUST_ALIGN 0
|
||||
#elif defined(__amd64) || defined(__amd64__)
|
||||
#define IWORDS_MUST_ALIGN 0
|
||||
#else
|
||||
#define IWORDS_MUST_ALIGN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
//=====================================================================
|
||||
@ -298,6 +309,7 @@ struct IKCPCB
|
||||
void *user;
|
||||
char *buffer;
|
||||
int fastresend;
|
||||
int fastlimit;
|
||||
int nocwnd, stream;
|
||||
int logmask;
|
||||
int (*output)(const char *buf, int len, struct IKCPCB *kcp, void *user);
|
||||
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
BIN
images/spatialos-25.png
Normal file
BIN
images/spatialos-25.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 79 KiB |
BIN
images/spatialos-50.png
Normal file
BIN
images/spatialos-50.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 86 KiB |
Loading…
Reference in New Issue
Block a user