Coder Social home page Coder Social logo

skywind3000 / kcp Goto Github PK

View Code? Open in Web Editor NEW
14.7K 14.7K 2.5K 523 KB

:zap: KCP - A Fast and Reliable ARQ Protocol

License: MIT License

C 80.09% C++ 17.53% CMake 2.38%
accelerator ack arq c kcp kcptun low-latency protocol quic rtc rtt socket srt tunnel udp

kcp's Introduction

KCP - A Fast and Reliable ARQ Protocol

Powered Build Status Backers on Open Collective Sponsors on Open Collective

README in English

简介

KCP是一个快速可靠协议,能以比 TCP 浪费 10%-20% 的带宽的代价,换取平均延迟降低 30%-40%,且最大延迟降低三倍的传输效果。纯算法实现,并不负责底层协议(如UDP)的收发,需要使用者自己定义下层数据包的发送方式,以 callback的方式提供给 KCP。 连时钟都需要外部传递进来,内部不会有任何一次系统调用。

整个协议只有 ikcp.h, ikcp.c两个源文件,可以方便的集成到用户自己的协议栈中。也许你实现了一个P2P,或者某个基于 UDP的协议,而缺乏一套完善的ARQ可靠协议实现,那么简单的拷贝这两个文件到现有项目中,稍微编写两行代码,即可使用。

技术特性

TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的是充分利用带宽。而 KCP是为流速设计的(单个数据包从一端发送到一端需要多少时间),以10%-20%带宽浪费的代价换取了比 TCP快30%-40%的传输速度。TCP信道是一条流速很慢,但每秒流量很大的大运河,而KCP是水流湍急的小激流。KCP有正常模式和快速模式两种,通过以下策略达到提高流速的结果:

RTO翻倍vs不翻倍:

TCP超时计算是RTOx2,这样连续丢三次包就变成RTOx8了,十分恐怖,而KCP启动快速模式后不x2,只是x1.5(实验证明1.5这个值相对比较好),提高了传输速度。

选择性重传 vs 全部重传:

TCP丢包时会全部重传从丢的那个包开始以后的数据,KCP是选择性重传,只重传真正丢失的数据包。

快速重传:

发送端发送了1,2,3,4,5几个包,然后收到远端的ACK: 1, 3, 4, 5,当收到ACK3时,KCP知道2被跳过1次,收到ACK4时,知道2被跳过了2次,此时可以认为2号丢失,不用等超时,直接重传2号包,大大改善了丢包时的传输速度。

延迟ACK vs 非延迟ACK:

TCP为了充分利用带宽,延迟发送ACK(NODELAY都没用),这样超时计算会算出较大 RTT时间,延长了丢包时的判断过程。KCP的ACK是否延迟发送可以调节。

UNA vs ACK+UNA:

ARQ模型响应有两种,UNA(此编号前所有包已收到,如TCP)和ACK(该编号包已收到),光用UNA将导致全部重传,光用ACK则丢失成本太高,以往协议都是二选其一,而 KCP协议中,除去单独的 ACK包外,所有包都有UNA信息。

非退让流控:

KCP正常模式同TCP一样使用公平退让法则,即发送窗口大小由:发送缓存大小、接收端剩余接收缓存大小、丢包退让及慢启动这四要素决定。但传送及时性要求很高的小数据时,可选择通过配置跳过后两步,仅用前两项来控制发送频率。以牺牲部分公平性及带宽利用率之代价,换取了开着BT都能流畅传输的效果。

快速安装

您可以使用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

基本使用

  1. 创建 KCP对象:

    // 初始化 kcp对象,conv为一个表示会话编号的整数,和tcp的 conv一样,通信双
    // 方需保证 conv相同,相互的数据包才能够被认可,user是一个给回调函数的指针
    ikcpcb *kcp = ikcp_create(conv, user);
  2. 设置回调函数:

    // KCP的下层协议输出函数,KCP需要发送数据时会调用它
    // buf/len 表示缓存和长度
    // user指针为 kcp对象创建时传入的值,用于区别多个 KCP对象
    int udp_output(const char *buf, int len, ikcpcb *kcp, void *user)
    {
      ....
    }
    // 设置回调函数
    kcp->output = udp_output;
  3. 循环调用 update:

    // 以一定频率调用 ikcp_update来更新 kcp状态,并且传入当前时钟(毫秒单位)
    // 如 10ms调用一次,或用 ikcp_check确定下次调用 update的时间不必每次调用
    ikcp_update(kcp, millisec);
  4. 输入一个下层数据包:

    // 收到一个下层数据包(比如UDP包)时需要调用:
    ikcp_input(kcp, received_udp_packet, received_udp_size);

    处理了下层协议的输出/输入后 KCP协议就可以正常工作了,使用 ikcp_send 来向 远端发送数据。而另一端使用 ikcp_recv(kcp, ptr, size)来接收数据。

协议配置

协议默认模式是一个标准的 ARQ,需要通过配置打开各项加速开关:

  1. 工作模式:

    int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc)
    • nodelay :是否启用 nodelay模式,0不启用;1启用。
    • interval :协议内部工作的 interval,单位毫秒,比如 10ms或者 20ms
    • resend :快速重传模式,默认0关闭,可以设置2(2次ACK跨越将会直接重传)
    • nc :是否关闭流控,默认是0代表不关闭,1代表关闭。
    • 普通模式: ikcp_nodelay(kcp, 0, 40, 0, 0);
    • 极速模式: ikcp_nodelay(kcp, 1, 10, 2, 1);
  2. 最大窗口:

    int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd);

    该调用将会设置协议的最大发送窗口和最大接收窗口大小,默认为32. 这个可以理解为 TCP的 SND_BUF 和 RCV_BUF,只不过单位不一样 SND/RCV_BUF 单位是字节,这个单位是包。

  3. 最大传输单元:

    纯算法协议并不负责探测 MTU,默认 mtu是1400字节,可以使用ikcp_setmtu来设置该值。该值将会影响数据包归并及分片时候的最大传输单元。

  4. 最小RTO:

    不管是 TCP还是 KCP计算 RTO时都有最小 RTO的限制,即便计算出来RTO为40ms,由于默认的 RTO是100ms,协议只有在100ms后才能检测到丢包,快速模式下为30ms,可以手动更改该值:

    kcp->rx_minrto = 10;

文档索引

协议的使用和配置都是很简单的,大部分情况看完上面的内容基本可以使用了。如果你需要进一步进行精细的控制,比如改变 KCP的内存分配器,或者你需要更有效的大规模调度 KCP链接(比如 3500个以上),或者如何更好的同 TCP结合,那么可以继续延伸阅读:

开源案例

  • kcptun: 基于 kcp-go做的高速远程端口转发(隧道) ,配合ssh -D,可以比 shadowsocks 更流畅的看在线视频。
  • dog-tunnel: GO开发的网络隧道,使用 KCP极大的改进了传输速度,并移植了一份 GO版本 KCP
  • v2ray: 著名代理软件,Shadowsocks 代替者,1.17后集成了 kcp协议,使用UDP传输,无数据包特征。
  • HP-Socket: 高性能网络通信框架 HP-Socket。
  • frp: 高性能内网穿透的反向代理软件,可将将内网服务暴露映射到外网服务器。
  • asio-kcp: 使用 KCP的完整 UDP网络库,完整实现了基于 UDP的链接状态管理,会话控制,KCP协议调度等
  • kcp-java: Java版本 KCP协议实现。
  • kcp-netty: kcp的Java语言实现,基于netty。
  • java-kcp: JAVA版本KCP,基于netty实现(包含fec功能)
  • csharp-kcp: csharp版本KCP,基于dotNetty实现(包含fec功能)
  • kcp-cpp: KCP 的多平台(Windows、MacOS、Linux)C++ 实现作为应用程序中的简单库。包含适用于所有平台的套接字处理和辅助函数。
  • kcp-perl: kcp的Perl实现,其是面向对象的,Perl-Like的。
  • kcp-go: 高安全性的kcp的 GO语言实现,包含 UDP会话管理的简单实现,可以作为后续开发的基础库。
  • kcp-csharp: kcp的 csharp移植,同时包含一份回话管理,可以连接上面kcp-go的服务端。
  • kcp-csharp: 新版本 Kcp的 csharp移植。线程安全,运行时无alloc,对gc无压力。
  • kcp2k: Line-by-line translation to C#, with optional Server/Client on top.
  • kcp-rs: KCP的 rust移植
  • kcp-rust:新版本 KCP的 rust 移植
  • tokio-kcp:rust tokio 的 kcp 集成
  • kcp-rust-native:rust 的 kcp bindings
  • lua-kcp: KCP的 Lua扩展,用于 Lua服务器
  • node-kcp: node-js 的 KCP 接口
  • nysocks: 基于libuv实现的node-addon,提供nodejs版本的代理服务,客户端接入支持SOCKS5和ss两种协议
  • shadowsocks-android: Shadowsocks for android 集成了 kcptun 使用 kcp协议加速 shadowsocks,效果不错
  • kcpuv: 使用 libuv开发的kcpuv库,目前还在 Demo阶段
  • Lantern:更好的 VPN,Github 50000 星,使用 kcpgo 加速
  • rpcx :RPC 框架,1000+ 星,使用 kcpgo 加速 RPC
  • xkcptun: c语言实现的kcptun,主要用于OpenWrt, LEDE开发的路由器项目上
  • et-frame: C#前后端框架(前端unity3d),统一用C#开发游戏,实现了前后端kcp协议
  • yasio: 一个跨平台专注于任意客户端程序的异步socket库, 易于使用,相同的API操作KCP/TCP/UDP, 性能测试结果: benchmark-pump.
  • gouxp: 用Go实现基于回调方式的KCP开发包,包含加解密和FEC支持,简单易用。
  • skcp: 基于libev实现的库,具备传输加密及基本的连接管理能力。
  • pykcp: Python 版本的 KCP 实现

商业案例

  • 原神:米哈游的《原神》使用 KCP 降低游戏消息的传输耗时,提升操作的体验。
  • SpatialOS: 大型多人分布式游戏服务端引擎,BigWorld 的后继者,使用 KCP 加速数据传输。
  • 西山居:使用 KCP 进行游戏数据加速。
  • CC:网易 CC 使用 kcp 加速视频推流,有效提高流畅性
  • BOBO:网易 BOBO 使用 kcp 加速主播推流
  • UU:网易 UU 加速器使用 KCP/KCPTUN 经行远程传输加速。
  • 阿里云:阿里云的视频传输加速服务 GRTN 使用 KCP 进行音视频数据传输优化,动态加速产品也使用 KCP。
  • 云帆加速:使用 KCP 加速文件传输和视频推流,优化了**主播推流的流畅度。
  • 明日帝国:Game K17 的 《明日帝国》 (Google Play),使用 KCP 加速游戏消息,让全球玩家流畅联网
  • 仙灵大作战:4399 的 MOBA游戏,使用 KCP 优化游戏同步

KCP 成功的运行在多个用户规模上亿的项目上,为他们提供了更加灵敏和丝滑网络体验。

欢迎告知更多案例

协议比较

如果网络永远不卡,那 KCP/TCP 表现类似,但是网络本身就是不可靠的,丢包和抖动无法避免(否则还要各种可靠协议干嘛)。在内网这种几乎理想的环境里直接比较,大家都差不多,但是放到公网上,放到3G/4G网络情况下,或者使用内网丢包模拟,差距就很明显了。公网在高峰期有平均接近10%的丢包,wifi/3g/4g下更糟糕,这些都会让传输变卡。

感谢 asio-kcp 的作者 zhangyuan 对 KCP 与 enet, udt做过的一次横向评测,结论如下:

  • ASIO-KCP has good performace in wifi and phone network(3G, 4G).
  • The kcp is the first choice for realtime pvp game.
  • The lag is less than 1 second when network lag happen. 3 times better than enet when lag happen.
  • The enet is a good choice if your game allow 2 second lag.
  • UDT is a bad idea. It always sink into badly situation of more than serval seconds lag. And the recovery is not expected.
  • enet has the problem of lack of doc. And it has lots of functions that you may intrest.
  • kcp's doc is chinese. Good thing is the function detail which is writen in code is english. And you can use asio_kcp which is a good wrap.
  • The kcp is a simple thing. You will write more code if you want more feature.
  • UDT has a perfect doc. UDT may has more bug than others as I feeling.

具体见:横向比较评测数据,为犹豫选择的人提供了更多指引。

大型多人游戏服务端引擎 SpatialOS 在集成 KCP 协议后做了同 TCP/RakNet 的评测:

对比了在服务端刷新率为 60 Hz 同时维护 50 个角色时的响应时间,详细对比报告见:

关于协议

近年来,网络游戏和各类社交网络都在成几何倍数的增长,不管网络游戏还是各类互动社交网络,交互性和复杂度都在迅速提高,都需要在极短的时间内将数据同时投递给大量用户,因此传输技术自然变为未来制约发展的一个重要因素,而开源界里各种著名的传输协议,如 raknet/enet 之类,一发布都是整套协议栈一起发布,这种形式是不利于多样化的,我的项目只能选择用或者不用你,很难选择 “部分用你”,然而你一套协议栈设计的再好,是非常难以满足不同角度的各种需求的。

因此 KCP 的方式是把协议栈 “拆开”,让大家可以根据项目需求进行灵活的调整和组装,你可以下面加一层 reed solomon 的纠删码做 FEC,上面加一层类 RC4/Salsa20 做流加密,握手处再设计一套非对称密钥交换,底层 UDP 传输层再做一套动态路由系统,同时探测多条路径,选最好路径进行传输。这些不同的 “协议单元” 可以像搭建积木一般根据需要自由组合,保证 “简单性” 和 “可拆分性”,这样才能灵活适配多变的业务需求,哪个模块不好,换了就是。

未来传输方面的解决方案必然是根据使用场景深度定制的,因此给大家一个可以自由组合的 “协议单元” ,方便大家集成在自己的协议栈中。

For more information, please see the Success Stories.

关于作者

作者:林伟 (skywind3000)

欢迎关注我的:twitterzhihu

我在多年的开发经历中,一直都喜欢研究解决程序中的一些瓶颈问题,早年喜欢游戏开发,照着《VGA编程》来做游戏图形,读 Michael Abrash 的《图形程序开发人员指南》做软渲染器,爱好摆弄一些能够榨干 CPU 能够运行更快的代码,参加工作后,兴趣转移到服务端和网络相关的技术。

2007 年时做了几个传统游戏后开始研究快速动作游戏的同步问题,期间写过不少文章,算是国内比较早研究同步问题的人,然而发现不管怎么解决同步都需要在网络传输方面有所突破,后来离开游戏转行互联网后也发现不少领域有这方面的需求,于是开始花时间在网络传输这个领域上,尝试基于 UDP 实现一些保守的可靠协议,仿照 BSD Lite 4.4 的代码实现一些类 TCP 协议,觉得比较有意思,又接着实现一些 P2P 和动态路由网相关的玩具。KCP 协议诞生于 2011 年,基本算是自己传输方面做的几个玩具中的一个。

Kcptun 的作者 xtaci 是我的大学同学,我俩都是学通信的,经常在一起研究如何进行传输优化。

欢迎捐赠

欢迎使用支付宝对该项目进行捐赠

欢迎使用支付宝手扫描上面的二维码,对该项目进行捐赠。捐赠款项将用于持续优化 KCP协议以及完善文档。

感谢:明明、星仔、进、帆、颁钊、斌铨、晓丹、余争、虎、晟敢、徐玮、王川、赵刚强、胡知锋、万新朝、何新超、刘旸、侯宪辉、吴佩仪、华斌、如涛、胡坚。。。(早先的名单实在不好意思没记录下来)等同学的捐助与支持。

欢迎关注

KCP交流群:364933586(QQ群号),KCP集成,调优,网络传输以及相关技术讨论

Gitter 群:https://gitter.im/skywind3000/KCP

blog: http://www.skywind.me

Contributors

This project exists thanks to all the people who contribute.

kcp's People

Contributors

andersc avatar b23r0 avatar chinsyo avatar egametang avatar enkiller avatar gyf19 avatar halx99 avatar homqyy avatar huahang avatar kumokyaku avatar l42111996 avatar liudf0716 avatar liuquanhao avatar losfair avatar miwarnec avatar monkeywithacupcake avatar myd7349 avatar oyyd avatar qxsoftware avatar realistikdash avatar shaoyuan1943 avatar shixiongfei avatar skywind3000 avatar szhnet avatar u2fsdgvkx1 avatar xboss avatar xtaci avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kcp's Issues

_itimediff 的定义是有意写成这样的?

当 later - earlier > 0x7FFFFFFF 时,_itimediff 会返回一个负值,而实际上 later 是大于 earlier 的。

比如 _itimediff(0xFFFFFFFF, 1)

static inline long _itimediff(IUINT32 later, IUINT32 earlier) 
{
    return ((IINT32)(later - earlier));
}

ikcp_recv 一直返回 -1

不知道是什么情况,在收到第一个正确的包后,接下来的包 一直返回-1.
是我发的太频繁了么?

iqueue_del空指针异常

1052a420-bfc3-412a-b35c-f105c2e53370

应用在iOS上,这个地方偶有crash,观察那时候node的prev和next都是NULL,这么说IQUEUE_DEL的宏是不是应该加上空指针判断?

超过慢启动阈值后,拥塞窗口的增加算法

        if (kcp->cwnd < kcp->ssthresh) {
            kcp->cwnd++;
            kcp->incr += mss;
        }   else {
            if (kcp->incr < mss) kcp->incr = mss;
            kcp->incr += (mss * mss) / kcp->incr + (mss / 16);
            if ((kcp->cwnd + 1) * mss >= kcp->incr) {
                kcp->cwnd++;
            }
        }

超过慢启动阈值后,拥塞窗口的增加算法是基于什么原理?要达到什么效果呢?能不能详细讲一讲。谢谢

关于feature里一些特性与tcp的比较

您好,咨询个问题

对于kcp feature里面列出的三个特性

  • 选择性重传 vs 全部重传
  • 快速重传
  • UNA vs ACK+UNA

对于开启了sack选项的tcp来说,这三点kcp是不是和tcp基本是一致的了?

Sending redundant data for lower latency on packet loss

This method is described well here http://gafferongames.com/building-a-game-network-protocol/reliable-ordered-messages/ .

In short, for example,

P1 == msg1 + msg2 + msg3
P2 == msg2 + msg3 + msg4
P3 == msg3 + msg4 + msg5

Then even if P2 is lost, msg4 can be recovered immediately by P3. This effectively multiples total data transmission size so it can't be for everything, but for sending small data periodically, it is a really effective method.

kcp的cwnd控制

kcp的cwnd控制为:
慢启动过程:
每收到一批数据,cwnd++
非慢启动过程:
每收到一批数据,cwnd+=1/cwnd+1/16
丢包:
cwnd/=2
请问理解是否正确?

ikcp_encode32u的字节序的转换为何没成功?

/* encode 32 bits unsigned int (lsb) */
static inline char *ikcp_encode32u(char *p, IUINT32 l)
{
#if IWORDS_BIG_ENDIAN
(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);
(unsigned char)(p + 3) = (unsigned char)((l >> 24) & 0xff);
#else
(IUINT32)p = l;
#endif
p += 4;
return p;
}

加上IWORDS_BIG_ENDIAN宏后,应该将p前4字节做字节序转换,但经测发现没转成功。

test.cpp 内存问题请教

@skywind3000 我们考察了其他类似的项目,这个项目最为简洁,感谢!

vs2015 本身有个内存快照的功能,用来查找内存泄露.
我跑了下test.cpp, 仅在147 行将 if (next > 1000) break; 改为 if (next > 100000) break;

然后抓取了两个时间点的内存快照信息,发现有大量68字节大小的内存未释放.

总览
image

堆栈:
image

是不是有什么需要注意的地方? 谢谢!

谁有例子

谁有例子 ,简单的能发能收就行
自己写的,速度上不来 ,两台机器 就几百K的速度
并且传时间长了 ,程序还崩溃了

关于WIKI中UDP连接不上的问题

在阅读WIKI(Cooperate With Tcp Server)的时候,文中写道,国内网络比较特殊,会存在有些UDP连接不上的情况。请教一下,在那些地区,或者哪些情况下,UDP会连接不上,存在这种问题的网络覆盖范围大吗?

关于fec

KCP只负责重传,并未加纠错,是不是因为公网传输时fec效果很有限,所以没必要?我们cto说公网里fec作用不大,我不知道是不是这样,请教skywind。谢谢!

RealTime PVP 有时候需要的是单MTU数据大小内最大序列号数据包有效

RealTime PVP 有时候需要的是单MTU数据大小内最大序列号数据包有效

例如玩家的位置,玩家可能发送了1,2,3,4,5,6一共6次位置。
而另一个玩家可能只收取到了1,3,5,6。当收到3的时候,因为比1大,因此3可以直接拿来使用,当2后来抵达后,会被忽略掉。客户端只关心刚收到的数据包的序号大于上一次数据包收到的序号。

因此在这种情况下,并不要求重发。
请问KCP能够通过参数调整实现这种模式吗?

我认为其在LAN应用场景的通讯意义远大于传统CS应用场景

在大公司里都有一套自己的底层通讯框架,比如腾讯的Apollo。
如果想做独立开发者,才会考虑使用KCP。但是独立开发者的技能往往侧重于前端开发,对于怎么管理连接,保持连接等经验是欠缺的,而且项目本身也用不上。所以,独立开发者往往适合使用UDP的方式通讯。
我看到Github上没有对KCP进行UDP化的封装,就着手弄了一个:KCPSocket。
你可以像使用UdpSocket一样使用KCP,真正达到像UDP一样方便,又像TCP一样可靠。

https://github.com/slicol/KCP-Socket

kcp 可以在手机端使用吗?

kcp 可以在手机端使用吗? 不知道大神有没有在uniy3d 项目集成过kcp? 如果可以的话, 最好可以来一个例子,谢谢

ikcp_send 后 output 不调用

       kcp = ikcp_create(0x11223344, (__bridge void *)(self));

        // 而考虑到丢包重发,设置最大收发窗口为128
        ikcp_wndsize(kcp, 128, 128);


        kcp->output = udp_output;

        ikcp_nodelay(kcp, 1, 10, 2, 1);
        kcp->rx_minrto = 10;
        kcp->fastresend = 1;


int udp_output(const char * buf, int len, ikcpcb * kcp, void * user)
{
    UDPSocket * socket = (__bridge UDPSocket *)(user);

    [socket.udpSendSocket sendData:[NSData dataWithBytes:buf length:len] toHost:host port:port withTimeout:-1 tag:0];

    printf(" --- udp send");

    return 0;
}


//编码完成后发送数据
- (void)ikcpSendData:(NSData *)data
{
    ikcp_update(kcp, [NSDate date].timeIntervalSince1970);
    int a = ikcp_send(kcp, data.bytes, sizeof(data.bytes));
    NSLog(@" -- ikcp_send => %d",a);
}

怎么使用

测试代码test.cpp中有模拟网络 什么意思 ,这个不能像TCP那样用吗,建立连接,IP,端口,为啥测试代码中看不到这些

做了 Node.js 扩展,希望能放置到【相关应用】中,还有关于版权协议的问题

Hi

感谢你贡献的 kcp 开源项目,我封装了 Node.js 扩展,项目地址在

https://github.com/leenjewel/node-kcp

希望能放置在 kcp 项目的 README 的【相关应用】列表中

最后,我看到你对项目使用了 GPL v2 协议,我使用了 Apache v2.0 协议,是有冲突的,考虑到 GPL 协议有些过于“强硬” ,是否能考虑更换可以兼容 Apache v2.0 的协议?

祝你愉快~

Do you accept donate?

Do you accept donate?

this is amazing protocol. like it very much

Do you accept donate?

Any idea for Obfuscate ?

Any idea for Obfuscate ?
We think about to using KCP , but need more security (less resource usage, no much more cpu and memory usage)

延迟ACK vs 非延迟ACK

README里有一段 "TCP为了充分利用带宽,延迟发送ACK(NODELAY都没用)", 有个选项TCP_QUICKACK可以控制,但是需要每次recv之后调用,有代价。这里不知道怎么描述可以更准确,吹毛求疵了,哈

包过大问题

如果一个包大小超过接收窗口大小,而窗口大小设置的值比255小,会出现一直无法接收的情况。因为部分数据包已经塞满了接收窗口,fr为0的包无法收到。这个问题怎么解决?

优化延迟,"延迟"的概念? RTT是网络链路固有属性

作者对延迟的定义是否存在歧义?
RTT,是网络链路的固有属性,传播时延是不可优化的,因为光速就那么点,链路长度除以光速,延迟是算的出来的。
“单个数据包从一端发送到一端需要多少时间”,不考虑协议栈,单纯算两端网卡发包和收包的时间间隔,是delay,是固有链路属性,受制于链路和队列。两端链路对称的情况下,是RTT/2.

作者对延迟的定义是?

针对ikcp_update的理解

不知道我理解的对不对哈, 客户端和服务端必须周期性的调用ikcp_update,来处理收发数据,如果不调用,就不会发送数据, 也就是说我必须开一个线程来调用ikcp_update,

还有个问题 对于实时性要求高,,数据包比较大,比如说视频流,,如何设置参数最优呢~

TCP转UDP保持长连接通信,请教KCP的参数设置问题

我在使用KCP做一个通信转换TCP-UDP-TCP的项目。我们的服务是基于TCP长连接的,但通常两端是异地的广域网,无法得到长时间稳定的TCP连接(例如难以超过24小时不断线),所以打算设计用UDP来完成中间通讯,两段分别对TCP进行转换为UDP。

流量是持续的、稳定的,峰值大约会有5Mbps,谷值大约500Kbps。ping延时范围大约是30ms ~ 100ms之间,取决于所在地域。

通讯中,数据的实时性是第一考虑要素。

Demo代码库是:https://github.com/btccom/BtcTunnel 。使用libevent作为事件通讯库。

想请教的问题是:

  • 对于这样的场景,ikcp_wndsize() / ikcp_nodelay() 如何设置会比较高效?
  • 不知 ikcp_update() 的调用方式是否正确?目前是:

还有一个现象是,当测试跨国(中美,丢包率5%15%,ping延时150ms250ms)通信的时候,数K的数据可以工作,然后数百K则无法正常工作,现象是 ikcp_recv() 先返回 –1, 然后数个 –2,然后就一直返回 –3 不知道是什么原因导致的?

联系方式

有没有作者留下联系方式,有问题想请教

请问KCP中是否使用了冗余校验?

TCP中使用了冗余校验,可以减少重传,而KCP的文档中貌似没有提及任何冗余校验机制,那我就估计KCP没有使用冗余校验。如果确实没有使用,那么请问这是为什么?谢谢!

ikcp_send 后 output 不调用

       kcp = ikcp_create(0x11223344, (__bridge void *)(self));

        // 而考虑到丢包重发,设置最大收发窗口为128
        ikcp_wndsize(kcp, 128, 128);


        kcp->output = udp_output;

        ikcp_nodelay(kcp, 1, 10, 2, 1);
        kcp->rx_minrto = 10;
        kcp->fastresend = 1;


int udp_output(const char * buf, int len, ikcpcb * kcp, void * user)
{
    UDPSocket * socket = (__bridge UDPSocket *)(user);

    [socket.udpSendSocket sendData:[NSData dataWithBytes:buf length:len] toHost:host port:port withTimeout:-1 tag:0];

    printf(" --- udp send");

    return 0;
}


//编码完成后发送数据
- (void)ikcpSendData:(NSData *)data
{
    ikcp_update(kcp, [NSDate date].timeIntervalSince1970);
    int a = ikcp_send(kcp, data.bytes, sizeof(data.bytes));
    NSLog(@" -- ikcp_send => %d",a);
}

编码完成后调用 ikcp_send ,返回值是0, 但是 udp_output 方法并没有被调用, 我看了下 ikcp_send 方法的代码,没有找到哪里会调用 kcpouput 方法。

memory leak

Hi, i have ran the asio_kcp in centos. But i found there is memory leak from server_lib. Do you know what may cause this... thanks!

I found ikcp_segment_new is called more times than ikcp_segment_delete! And i used free to see the mem status as follows...


[root@ ~]# free
total used free shared buffers cached
Mem: 1922244 237748 1684496 0 12260 155564
-/+ buffers/cache: 69924 1852320
Swap: 0 0 0
[root@ ~]# free
total used free shared buffers cached
Mem: 1922244 238104 1684140 0 12268 155972
-/+ buffers/cache: 69864 1852380
Swap: 0 0 0
[root@ ~]# free
total used free shared buffers cached
Mem: 1922244 250132 1672112 0 12532 167364
-/+ buffers/cache: 70236 1852008
Swap: 0 0 0

描述有一丝歧义

如果永远不丢包那么 KCP和 TCP性能差不多,但网络会卡,造成卡的原因就是丢包和抖动。

这句话有歧义,对KCP不了解的人从字面看上去,“网络会卡”可能是KCP造成的。是不是可以表述成“ 如果网络永远不丢包不抖动,那么 KCP和 TCP性能差不多。”

使用哪种FEC最高效,请指点。

目前已知的FEC方案包括:
1、openfec.org
2、tahoe-lafs.org/trac/zfec
3、Reed Solomon

哪种FEC理论上最能优化传输效率、避免重传呢?还是有我不知道的更好方案?还是哪两种结合使用?请您指点。

关于奇怪的参数产生的问题

kcp1:lkcp_wndsize(6400, 6400)
kcp1:lkcp_nodelay(1, 5, 2, 1)设置一样
sleep(0)设置为0,客户端连续发包2000个长度20,接收完时间为10ms tcp为14ms
可是cpu比较高,sleep改为1的话相当于10ms的休眠,然后结果就变的19000ms才接收完2000个包
这个差距有点大的离谱

KCP和TCP的比较

我尝试了一把KCP,测试KCP和TCP的延时情况,测试方法和自带的测试程序相似:

每20ms发送一个1k的数据包,发送1000次,统计数据来回的最大延时和平均延时
KCP配置为快速模式,TCP和KCP服务器都为简单的echo服务,每1ms调用一次updata()

**1.**在内网环境下,KCP完全没有优势,TCP的平均延时小于1ms,kcp的延时约9ms

**2.**在外网(有线)环境下,平均延时TCP(7ms),KCP(15ms)依然没有优势,只是KCP(50ms)的最大延时小于TCP(秒级),且没有大的抖动,TCP有时会出现秒级的延时,而KCP很少出现这种情况

**3.**在4G环境下(移动4G),和外网环境下测试结果相似,KCP(65ms)的平均延时高于TCP(55ms),同样的,TCP(1秒左右)比KCP(350ms)有更大的抖动

**4.**我现在应用场景是客户端(手机)一发一收(需要收到回应才发下一个包),约30次小于1k的数据交互,其中有几次交互需要延时小于90ms,目前用TCP有失败的概率,想用KCP改善(降低整个流程的交互时间,提高用户体验,减少失败概率)

**5.**从结果上来看,KCP显得很鸡肋,从移动应用的角度看,他花费了更多的流量,并没有换取延时的降低(指平均延时)

**6.**可能是我测试程序不能体现出KCP的优势,我想知道您是 怎么测试得出 “能以比 TCP浪费10%-20%的带宽的代价,换取平均延迟降低 30%-40%” ,或者源码的目录里能否把这份测试程序公开,这样我也能比较信服的接受

**7.**如果只是做收发数据耗时的测试(10M数据测试,每个包1k),TCP是一发一收数据的统计和,而UDP并非一发一收,单个数据包来回的延时都是秒级的,但总的耗时是低于TCP的,只有TCP的20%,但如果KCP也写成收到一个包才发送下一个包的话,两者并没有多少差距

写了很多,1是希望得到解答,2是希望楼主能把KCP的应用场景再明确一下

ICONTAINEROF 宏定义的疑惑

大神您好!我研读您的 kcp 协议代码,发现一处地方不太明白,具体是 ikcp.h 的 156~157 行。如下:

#define ICONTAINEROF(ptr, type, member) ( \
	(type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) )

这里 ptr 是指向 member 的指针,而 type 是包含 member 成员的父结构类型,所以 (char*)((type*)ptr) 这个强制转换为 type* 的过程感觉有点儿奇怪,感觉有点儿多余。不知是否有什么特殊的技巧还是纯粹多写了一个强制转换?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.