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.
- [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:
![](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
See [Success Stories](https://github.com/skywind3000/kcp/wiki/Success-Stories).
# 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.

View File

@ -1,8 +1,8 @@
KCP - A Fast and Reliable ARQ Protocol
======================================
[![Powered][2]][1] [![Build Status][4]][5]
[![Backers on Open Collective](https://opencollective.com/kcp/backers/badge.svg)](#backers)
[![Powered][2]][1] [![Build Status][4]][5]
[![Backers on Open Collective](https://opencollective.com/kcp/backers/badge.svg)](#backers)
[![Sponsors on Open Collective](https://opencollective.com/kcp/sponsors/badge.svg)](#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 的评测:
![](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协议以及完善文档。

47
ikcp.c
View File

@ -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
View File

@ -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);

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