This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
最佳实践
内存分配器
默认KCP协议使用 malloc/free进行内存分配释放,如果应用层接管了内存分配,可以用ikcp_allocator来设置新的内存分配器,注意要在一开始设置:
ikcp_allocator(my_new_malloc, my_new_free);
前向纠错注意
为了进一步提高传输速度,下层协议也许会使用前向纠错技术。需要注意,前向纠错会根据冗余信息解出原始数据包。相同的原始数据包不要两次input到KCP,否则将会导致 kcp以为对方重发了,这样会产生更多的ack占用额外带宽。
比如下层协议使用最简单的冗余包:单个数据包除了自己外,还会重复存储一次上一个数据包,以及上上一个数据包的内容:
Fn = (Pn, Pn-1, Pn-2)
P0 = (0, X, X)
P1 = (1, 0, X)
P2 = (2, 1, 0)
P3 = (3, 2, 1)
这样几个包发送出去,接收方对于单个原始包都可能被解出3次来(后面两个包任然会重复该包内容),那么这里需要记录一下,一个下层数据包只会input给kcp一次,避免过多重复ack带来的浪费。
管理大规模连接
如果需要同时管理大规模的 KCP连接(比如大于3000个),比如你正在实现一套类 epoll的机制,那么为了避免每秒钟对每个连接调用大量的调用 ikcp_update,我们可以使用 ikcp_check 来大大减少 ikcp_update调用的次数。 ikcp_check返回值会告诉你需要在什么时间点再次调用 ikcp_update(如果中途没有 ikcp_send, ikcp_input的话,否则中途调用了 ikcp_send, ikcp_input的话,需要在下一次interval时调用 update)
标准顺序是每次调用了 ikcp_update后,使用 ikcp_check决定下次什么时间点再次调用 ikcp_update,而如果中途发生了 ikcp_send, ikcp_input 的话,在下一轮 interval 立马调用 ikcp_update和 ikcp_check。 使用该方法,原来在处理2000个 kcp连接且每 个连接每10ms调用一次update,改为 check机制后,cpu从 60%降低到 15%。
避免缓存积累延迟
不管是 TCP/KCP,信道能力在那里放着,让你没法无限制的调用 send,请阅读:“如何避免缓存积累延迟” 这篇 wiki。
协议栈分层组装
不要试图将任何加密或者 FEC相关代码实现到 KCP里面,请实现成不同协议单元并组装成你的协议栈,具体请看:协议栈分层组装
如何支持收发可靠和非可靠数据?
有的产品可能除了需要可靠数据,还需要发送非可靠数据,那么 KCP 如何支持这种需求呢?很简单,你自己实现:
connection.send(channel, pkt, size);
channel == 0 使用 kcp 发送可靠包,channel == 1 使用 udp 发送非可靠包。
因为传输是你自己实现的,你可以在发送UDP包的头部加一个字节,来代表这个 channel
,收到远程来的 UDP以后,也可以判断 channel==0 的话,把剩下的数据给 ikcp_input
,否则剩下的数据为远程非可靠包。
这样你得到了一个新的发送函数,用channel来区别你想发送可靠数据还是非可靠数据。再统一封装一个 connection.recv
函数,先去 ikcp_recv
那里尝试收包,收不到的话,看刚才有没有收到 channel=1 的裸UDP包,有的话返回给上层用户。
如果你的服务端是混用 tcp/udp 的话,你还可以设计个 channel=2 使用 TCP 发送数据,针对一些比较大的,延迟不敏感的东西。