This commit is contained in:
skywind3000 2019-08-06 21:30:49 +08:00
commit 234239b9e2
7 changed files with 70 additions and 19 deletions

View File

@ -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. - [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-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. - [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-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-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 - [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. 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:
![](https://raw.githubusercontent.com/skywind3000/kcp/master/images/spatialos-50.png)
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 # KCP is used by
See [Success Stories](https://github.com/skywind3000/kcp/wiki/Success-Stories). See [Success Stories](https://github.com/skywind3000/kcp/wiki/Success-Stories).
# Donation # Donation
![欢迎使用支付宝对该项目进行捐赠](https://raw.githubusercontent.com/skywind3000/kcp/master/donation.png) ![欢迎使用支付宝对该项目进行捐赠](https://raw.githubusercontent.com/skywind3000/kcp/master/images/donation.png)
Donation is welcome by using alipay, the money will be used to improve the protocol and documentation. Donation is welcome by using alipay, the money will be used to improve the protocol and documentation.

View File

@ -146,6 +146,7 @@ TCP是为流量设计的每秒内可以传输多少KB的数据讲究的
- [asio-kcp](https://github.com/libinzhangyuan/asio_kcp): 使用 KCP的完整 UDP网络库完整实现了基于 UDP的链接状态管理会话控制KCP协议调度等 - [asio-kcp](https://github.com/libinzhangyuan/asio_kcp): 使用 KCP的完整 UDP网络库完整实现了基于 UDP的链接状态管理会话控制KCP协议调度等
- [kcp-java](https://github.com/hkspirt/kcp-java)Java版本 KCP协议实现。 - [kcp-java](https://github.com/hkspirt/kcp-java)Java版本 KCP协议实现。
- [kcp-netty](https://github.com/szhnet/kcp-netty)kcp的Java语言实现基于netty。 - [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-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/limpo1989/kcp-csharp): kcp的 csharp移植同时包含一份回话管理可以连接上面kcp-go的服务端。
- [kcp-csharp](https://github.com/KumoKyaku/KCP): 新版本 Kcp的 csharp移植。线程安全运行时无alloc对gc无压力。 - [kcp-csharp](https://github.com/KumoKyaku/KCP): 新版本 Kcp的 csharp移植。线程安全运行时无alloc对gc无压力。
@ -169,6 +170,7 @@ TCP是为流量设计的每秒内可以传输多少KB的数据讲究的
- [CC](http://cc.163.com/):网易 CC 使用 kcp 加速视频推流,有效提高流畅性 - [CC](http://cc.163.com/):网易 CC 使用 kcp 加速视频推流,有效提高流畅性
- [BOBO](http://bobo.163.com/):网易 BOBO 使用 kcp 加速主播推流 - [BOBO](http://bobo.163.com/):网易 BOBO 使用 kcp 加速主播推流
- [云帆加速](http://www.yfcloud.com/):使用 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),为犹豫选择的人提供了更多指引。 具体见:[横向比较](https://github.com/libinzhangyuan/reliable_udp_bench_mark) 和 [评测数据](https://github.com/skywind3000/kcp/wiki/KCP-Benchmark),为犹豫选择的人提供了更多指引。
大型多人游戏服务端引擎 [SpatialOS](https://improbable.io/spatialOS) 在集成 KCP 协议后做了同 TCP/RakNet 的评测:
![](https://raw.githubusercontent.com/skywind3000/kcp/master/images/spatialos-50.png)
对比了在服务端刷新率为 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).
# 欢迎捐赠 # 欢迎捐赠
![欢迎使用支付宝对该项目进行捐赠](https://raw.githubusercontent.com/skywind3000/kcp/master/donation.png) ![欢迎使用支付宝对该项目进行捐赠](https://raw.githubusercontent.com/skywind3000/kcp/master/images/donation.png)
欢迎使用支付宝手扫描上面的二维码,对该项目进行捐赠。捐赠款项将用于持续优化 KCP协议以及完善文档。 欢迎使用支付宝手扫描上面的二维码,对该项目进行捐赠。捐赠款项将用于持续优化 KCP协议以及完善文档。

37
ikcp.c
View File

@ -43,6 +43,7 @@ const IUINT32 IKCP_THRESH_INIT = 2;
const IUINT32 IKCP_THRESH_MIN = 2; const IUINT32 IKCP_THRESH_MIN = 2;
const IUINT32 IKCP_PROBE_INIT = 7000; // 7 secs to probe window size 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_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) */ /* encode 16 bits unsigned int (lsb) */
static inline char *ikcp_encode16u(char *p, unsigned short w) 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 + 0) = (w & 255);
*(unsigned char*)(p + 1) = (w >> 8); *(unsigned char*)(p + 1) = (w >> 8);
#else #else
@ -79,7 +80,7 @@ static inline char *ikcp_encode16u(char *p, unsigned short w)
/* decode 16 bits unsigned int (lsb) */ /* decode 16 bits unsigned int (lsb) */
static inline const char *ikcp_decode16u(const char *p, unsigned short *w) 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 + 1);
*w = *(const unsigned char*)(p + 0) + (*w << 8); *w = *(const unsigned char*)(p + 0) + (*w << 8);
#else #else
@ -92,7 +93,7 @@ static inline const char *ikcp_decode16u(const char *p, unsigned short *w)
/* encode 32 bits unsigned int (lsb) */ /* encode 32 bits unsigned int (lsb) */
static inline char *ikcp_encode32u(char *p, IUINT32 l) 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 + 0) = (unsigned char)((l >> 0) & 0xff);
*(unsigned char*)(p + 1) = (unsigned char)((l >> 8) & 0xff); *(unsigned char*)(p + 1) = (unsigned char)((l >> 8) & 0xff);
*(unsigned char*)(p + 2) = (unsigned char)((l >> 16) & 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) */ /* decode 32 bits unsigned int (lsb) */
static inline const char *ikcp_decode32u(const char *p, IUINT32 *l) 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 + 3);
*l = *(const unsigned char*)(p + 2) + (*l << 8); *l = *(const unsigned char*)(p + 2) + (*l << 8);
*l = *(const unsigned char*)(p + 1) + (*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->logmask = 0;
kcp->ssthresh = IKCP_THRESH_INIT; kcp->ssthresh = IKCP_THRESH_INIT;
kcp->fastresend = 0; kcp->fastresend = 0;
kcp->fastlimit = IKCP_FASTACK_LIMIT;
kcp->nocwnd = 0; kcp->nocwnd = 0;
kcp->xmit = 0; kcp->xmit = 0;
kcp->dead_link = IKCP_DEADLINK; 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; struct IQUEUEHEAD *p, *next;
@ -618,7 +620,12 @@ static void ikcp_parse_fastack(ikcpcb *kcp, IUINT32 sn)
break; break;
} }
else if (sn != seg->sn) { else if (sn != seg->sn) {
#ifndef IKCP_FASTACK_CONSERVE
seg->fastack++; 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) int ikcp_input(ikcpcb *kcp, const char *data, long size)
{ {
IUINT32 una = kcp->snd_una; IUINT32 prev_una = kcp->snd_una;
IUINT32 maxack = 0; IUINT32 maxack = 0, latest_ts = 0;
int flag = 0; int flag = 0;
if (ikcp_canlog(kcp, IKCP_LOG_INPUT)) { if (ikcp_canlog(kcp, IKCP_LOG_INPUT)) {
@ -791,9 +798,18 @@ int ikcp_input(ikcpcb *kcp, const char *data, long size)
if (flag == 0) { if (flag == 0) {
flag = 1; flag = 1;
maxack = sn; maxack = sn;
latest_ts = ts;
} else { } else {
if (_itimediff(sn, maxack) > 0) { if (_itimediff(sn, maxack) > 0) {
#ifndef IKCP_FASTACK_CONSERVE
maxack = sn; 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)) { 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) { 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) { if (kcp->cwnd < kcp->rmt_wnd) {
IUINT32 mss = kcp->mss; IUINT32 mss = kcp->mss;
if (kcp->cwnd < kcp->ssthresh) { if (kcp->cwnd < kcp->ssthresh) {
@ -1048,12 +1064,15 @@ void ikcp_flush(ikcpcb *kcp)
lost = 1; lost = 1;
} }
else if (segment->fastack >= resent) { else if (segment->fastack >= resent) {
if ((int)segment->xmit <= kcp->fastlimit ||
kcp->fastlimit <= 0) {
needsend = 1; needsend = 1;
segment->xmit++; segment->xmit++;
segment->fastack = 0; segment->fastack = 0;
segment->resendts = current + segment->rto; segment->resendts = current + segment->rto;
change++; change++;
} }
}
if (needsend) { if (needsend) {
int size, need; int size, need;

14
ikcp.h
View File

@ -225,7 +225,7 @@ typedef struct IQUEUEHEAD iqueue_head;
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// WORD ORDER // BYTE ORDER & ALIGNMENT
//--------------------------------------------------------------------- //---------------------------------------------------------------------
#ifndef IWORDS_BIG_ENDIAN #ifndef IWORDS_BIG_ENDIAN
#ifdef _BIG_ENDIAN_ #ifdef _BIG_ENDIAN_
@ -248,6 +248,17 @@ typedef struct IQUEUEHEAD iqueue_head;
#endif #endif
#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; void *user;
char *buffer; char *buffer;
int fastresend; int fastresend;
int fastlimit;
int nocwnd, stream; int nocwnd, stream;
int logmask; int logmask;
int (*output)(const char *buf, int len, struct IKCPCB *kcp, void *user); int (*output)(const char *buf, int len, struct IKCPCB *kcp, void *user);

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
images/spatialos-25.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
images/spatialos-50.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB