mirror of
https://github.com/skywind3000/kcp.git
synced 2024-12-26 07:00:09 +08:00
commit
14c6beb88d
@ -1,11 +1,31 @@
|
||||
PROJECT(kcp)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
project(kcp LANGUAGES C)
|
||||
|
||||
include(CTest)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
add_library(kcp STATIC ikcp.c)
|
||||
|
||||
add_executable(kcp_test test.cpp)
|
||||
|
||||
|
||||
install(FILES ikcp.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
install(TARGETS kcp
|
||||
EXPORT kcp-targets
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
install(EXPORT kcp-targets
|
||||
FILE kcp-config.cmake
|
||||
NAMESPACE kcp::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/kcp
|
||||
)
|
||||
|
||||
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 ()
|
||||
|
25
README.en.md
25
README.en.md
@ -47,6 +47,18 @@ There are two kinds of ARQ model responses: UNA (All packets before this number
|
||||
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.
|
||||
|
||||
|
||||
# Quick Install
|
||||
|
||||
You can download and install kcp using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./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.
|
||||
|
||||
# Basic Usage
|
||||
|
||||
1. Create KCP object:
|
||||
@ -144,10 +156,11 @@ Both the use and configuration of the protocol is very simple, in most cases, af
|
||||
- [dog-tunnel](https://github.com/vzex/dog-tunnel): Network tunnel developed by GO, using KCP to greatly improve the transmission speed, and migrated a GO version of the KCP.
|
||||
- [v2ray](https://www.v2ray.com):Well-known proxy software, Shadowsocks replacement, integrated with kcp protocol after 1.17, using UDP transmission, no data packet features.
|
||||
- [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-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)
|
||||
- [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
|
||||
@ -177,13 +190,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.
|
||||
|
||||
|
59
README.md
59
README.md
@ -49,6 +49,18 @@ TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的
|
||||
KCP正常模式同TCP一样使用公平退让法则,即发送窗口大小由:发送缓存大小、接收端剩余接收缓存大小、丢包退让及慢启动这四要素决定。但传送及时性要求很高的小数据时,可选择通过配置跳过后两步,仅用前两项来控制发送频率。以牺牲部分公平性及带宽利用率之代价,换取了开着BT都能流畅传输的效果。
|
||||
|
||||
|
||||
# 快速安装
|
||||
|
||||
您可以使用[vcpkg](https://github.com/Microsoft/vcpkg)库管理器下载并安装kcp:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
./vcpkg install kcp
|
||||
|
||||
vcpkg中的kcp库由Microsoft团队成员和社区贡献者保持最新状态。如果版本过时,请在vcpkg存储库上[创建issue或提出PR](https://github.com/Microsoft/vcpkg)。
|
||||
|
||||
# 基本使用
|
||||
|
||||
1. 创建 KCP对象:
|
||||
@ -141,12 +153,13 @@ TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的
|
||||
|
||||
- [kcptun](https://github.com/xtaci/kcptun): 基于 kcp-go做的高速远程端口转发(隧道) ,配合ssh -D,可以比 shadowsocks 更流畅的看在线视频。
|
||||
- [dog-tunnel](https://github.com/vzex/dog-tunnel): GO开发的网络隧道,使用 KCP极大的改进了传输速度,并移植了一份 GO版本 KCP
|
||||
- [v2ray](https://www.v2ray.com):著名代理软件,Shadowsocks 代替者,1.17后集成了 kcp协议,使用UDP传输,无数据包特征。
|
||||
- [HP-Socket](https://github.com/ldcsaa/HP-Socket):高性能网络通信框架 HP-Socket。
|
||||
- [v2ray](https://www.v2ray.com): 著名代理软件,Shadowsocks 代替者,1.17后集成了 kcp协议,使用UDP传输,无数据包特征。
|
||||
- [HP-Socket](https://github.com/ldcsaa/HP-Socket): 高性能网络通信框架 HP-Socket。
|
||||
- [frp](https://github.com/fatedier/frp): 高性能内网穿透的反向代理软件,可将将内网服务暴露映射到外网服务器。
|
||||
- [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-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无压力。
|
||||
@ -170,6 +183,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 加速数据传输。
|
||||
|
||||
欢迎告知更多案例
|
||||
|
||||
@ -191,12 +205,41 @@ 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)
|
||||
|
||||
|
||||
# 关于协议
|
||||
|
||||
近年来,网络游戏和各类社交网络都在成几何倍数的增长,不管网络游戏还是各类互动社交网络,交互性和复杂度都在迅速提高,都需要在极短的时间内将数据同时投递给大量用户,因此传输技术自然变为未来制约发展的一个重要因素,而开源界里各种著名的传输协议,如 raknet/enet 之类,一发布都是整套协议栈一起发布,这种形式是不利于多样化的,我的项目只能选择用或者不用你,很难选择 “部分用你”,然而你一套协议栈设计的再好,是非常难以满足不同角度的各种需求的。
|
||||
|
||||
因此 KCP 的方式是把协议栈 “拆开”,让大家可以根据项目需求进行灵活的调整和组装,你可以下面加一层 reed solomon 的纠删码做 FEC,上面加一层类 RC4/Salsa20 做流加密,握手处再设计一套非对称密钥交换,底层 UDP 传输层再做一套动态路由系统,同时探测多条路径,选最好路径进行传输。这些不同的 “协议单元” 可以像搭建积木一般根据需要自由组合,保证 “简单性” 和 “可拆分性”,这样才能灵活适配多变的业务需求,哪个模块不好,换了就是。
|
||||
|
||||
未来传输方面的解决方案必然是根据使用场景深度定制的,因此给大家一个可以自由组合的 “协议单元” ,方便大家集成在自己的协议栈中。
|
||||
|
||||
For more information, please see the [Success Stories](https://github.com/skywind3000/kcp/wiki/Success-Stories).
|
||||
|
||||
|
||||
# 关于作者
|
||||
|
||||
作者:林伟 (skywind3000)
|
||||
|
||||
欢迎关注我的:[twitter](https://twitter.com/skywind3000) 和 [zhihu](https://www.zhihu.com/people/skywind3000)。
|
||||
|
||||
我在多年的开发经历中,一直都喜欢研究解决程序中的一些瓶颈问题,早年喜欢游戏开发,照着《VGA编程》来做游戏图形,读 Michael Abrash 的《图形程序开发人员指南》做软渲染器,爱好摆弄一些能够榨干 CPU 能够运行更快的代码,参加工作后,兴趣转移到服务端和网络相关的技术。
|
||||
|
||||
2007 年时做了几个传统游戏后开始研究快速动作游戏的同步问题,期间写过不少文章,算是国内比较早研究同步问题的人,然而发现不管怎么解决同步都需要在网络传输方面有所突破,后来离开游戏转行互联网后也发现不少领域有这方面的需求,于是开始花时间在网络传输这个领域上,尝试基于 UDP 实现一些保守的可靠协议,反照 BSD Lite 4.4 的代码实现一些类 TCP 协议,觉得比较有意思,又接着实现一些 P2P 和动态路由网相关的玩具。KCP 协议诞生于 2011 年,基本算是自己传输方面做的几个玩具中的一个。
|
||||
|
||||
Kcptun 的作者 xtaci 是我的大学同学,我俩都是学通信的,经常在一起研究如何进行传输优化。
|
||||
|
||||
# 欢迎捐赠
|
||||
|
||||
![欢迎使用支付宝对该项目进行捐赠](https://raw.githubusercontent.com/skywind3000/kcp/master/donation.png)
|
||||
![欢迎使用支付宝对该项目进行捐赠](images/donation.png)
|
||||
|
||||
欢迎使用支付宝手扫描上面的二维码,对该项目进行捐赠。捐赠款项将用于持续优化 KCP协议以及完善文档。
|
||||
|
||||
@ -206,13 +249,11 @@ TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的
|
||||
欢迎关注
|
||||
|
||||
KCP交流群:364933586(QQ群号),KCP集成,调优,网络传输以及相关技术讨论
|
||||
|
||||
Gitter 群:https://gitter.im/skywind3000/KCP
|
||||
|
||||
blog: http://www.skywind.me
|
||||
|
||||
zhihu: https://www.zhihu.com/people/skywind3000
|
||||
|
||||
|
||||
|
||||
|
||||
## Contributors
|
||||
|
BIN
benchmark.png
Normal file
BIN
benchmark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 165 KiB |
71
ikcp.c
71
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
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
@ -70,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;
|
||||
@ -83,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;
|
||||
@ -98,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;
|
||||
@ -113,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;
|
||||
@ -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;
|
||||
@ -393,7 +395,7 @@ int ikcp_recv(ikcpcb *kcp, char *buffer, int len)
|
||||
fragment = seg->frg;
|
||||
|
||||
if (ikcp_canlog(kcp, IKCP_LOG_RECV)) {
|
||||
ikcp_log(kcp, IKCP_LOG_RECV, "recv sn=%lu", seg->sn);
|
||||
ikcp_log(kcp, IKCP_LOG_RECV, "recv sn=%lu", (unsigned long)seg->sn);
|
||||
}
|
||||
|
||||
if (ispeek == 0) {
|
||||
@ -410,7 +412,7 @@ int ikcp_recv(ikcpcb *kcp, char *buffer, int len)
|
||||
|
||||
// move available data from rcv_buf -> rcv_queue
|
||||
while (! iqueue_is_empty(&kcp->rcv_buf)) {
|
||||
IKCPSEG *seg = iqueue_entry(kcp->rcv_buf.next, IKCPSEG, node);
|
||||
seg = iqueue_entry(kcp->rcv_buf.next, IKCPSEG, node);
|
||||
if (seg->sn == kcp->rcv_nxt && kcp->nrcv_que < kcp->rcv_wnd) {
|
||||
iqueue_del(&seg->node);
|
||||
kcp->nrcv_buf--;
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -742,11 +749,11 @@ void ikcp_parse_data(ikcpcb *kcp, IKCPSEG *newseg)
|
||||
int ikcp_input(ikcpcb *kcp, const char *data, long size)
|
||||
{
|
||||
IUINT32 prev_una = kcp->snd_una;
|
||||
IUINT32 maxack = 0;
|
||||
IUINT32 maxack = 0, latest_ts = 0;
|
||||
int flag = 0;
|
||||
|
||||
if (ikcp_canlog(kcp, IKCP_LOG_INPUT)) {
|
||||
ikcp_log(kcp, IKCP_LOG_INPUT, "[RI] %d bytes", size);
|
||||
ikcp_log(kcp, IKCP_LOG_INPUT, "[RI] %d bytes", (int)size);
|
||||
}
|
||||
|
||||
if (data == NULL || (int)size < (int)IKCP_OVERHEAD) return -1;
|
||||
@ -791,14 +798,23 @@ 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)) {
|
||||
ikcp_log(kcp, IKCP_LOG_IN_DATA,
|
||||
"input ack: sn=%lu rtt=%ld rto=%ld", sn,
|
||||
ikcp_log(kcp, IKCP_LOG_IN_ACK,
|
||||
"input ack: sn=%lu rtt=%ld rto=%ld", (unsigned long)sn,
|
||||
(long)_itimediff(kcp->current, ts),
|
||||
(long)kcp->rx_rto);
|
||||
}
|
||||
@ -806,7 +822,7 @@ int ikcp_input(ikcpcb *kcp, const char *data, long size)
|
||||
else if (cmd == IKCP_CMD_PUSH) {
|
||||
if (ikcp_canlog(kcp, IKCP_LOG_IN_DATA)) {
|
||||
ikcp_log(kcp, IKCP_LOG_IN_DATA,
|
||||
"input psh: sn=%lu ts=%lu", sn, ts);
|
||||
"input psh: sn=%lu ts=%lu", (unsigned long)sn, (unsigned long)ts);
|
||||
}
|
||||
if (_itimediff(sn, kcp->rcv_nxt + kcp->rcv_wnd) < 0) {
|
||||
ikcp_ack_push(kcp, sn, ts);
|
||||
@ -841,7 +857,7 @@ int ikcp_input(ikcpcb *kcp, const char *data, long size)
|
||||
// do nothing
|
||||
if (ikcp_canlog(kcp, IKCP_LOG_IN_WINS)) {
|
||||
ikcp_log(kcp, IKCP_LOG_IN_WINS,
|
||||
"input wins: %lu", (IUINT32)(wnd));
|
||||
"input wins: %lu", (unsigned long)(wnd));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -853,7 +869,7 @@ 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, prev_una) > 0) {
|
||||
@ -866,7 +882,11 @@ int ikcp_input(ikcpcb *kcp, const char *data, long size)
|
||||
if (kcp->incr < mss) kcp->incr = mss;
|
||||
kcp->incr += (mss * mss) / kcp->incr + (mss / 16);
|
||||
if ((kcp->cwnd + 1) * mss <= kcp->incr) {
|
||||
#if 1
|
||||
kcp->cwnd = (kcp->incr + mss - 1) / ((mss > 0)? mss : 1);
|
||||
#else
|
||||
kcp->cwnd++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (kcp->cwnd > kcp->rmt_wnd) {
|
||||
@ -1040,23 +1060,28 @@ 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;
|
||||
}
|
||||
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) {
|
||||
int size, need;
|
||||
int need;
|
||||
segment->ts = current;
|
||||
segment->wnd = seg.wnd;
|
||||
segment->una = kcp->rcv_nxt;
|
||||
@ -1077,7 +1102,7 @@ void ikcp_flush(ikcpcb *kcp)
|
||||
}
|
||||
|
||||
if (segment->xmit >= kcp->dead_link) {
|
||||
kcp->state = -1;
|
||||
kcp->state = (IUINT32)-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
ikcp.h
1
ikcp.h
@ -309,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 |
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
|
||||
*/
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user