From 48c759ccd8f40cfefe0feb0257535a50571c8fb5 Mon Sep 17 00:00:00 2001 From: skywind3000 <skywind3000@163.com> Date: Tue, 30 Dec 2014 22:31:53 +0800 Subject: [PATCH] new document --- README.md | 54 ++++++++++++++++++++++++++++++------------------- doc/donate.png | Bin 0 -> 5362 bytes ikcp.c | 17 ++++++++-------- ikcp.h | 17 ++++++++-------- 4 files changed, 50 insertions(+), 38 deletions(-) create mode 100644 doc/donate.png diff --git a/README.md b/README.md index a464639..f977c41 100644 --- a/README.md +++ b/README.md @@ -103,24 +103,21 @@ TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的 协议默认模式是一个标准的 ARQ,需要通过配置打开各项加速开关: 1. 工作模式: + ```cpp + int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc) + ``` - 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); + > 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); + ```cpp + int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd); + ``` 该调用将会设置协议的最大发送窗口和最大接收窗口大小,默认为32. 3. 最大传输单元: @@ -133,9 +130,9 @@ TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的 不管是 TCP还是 KCP计算 RTO时都有最小 RTO的限制,即便计算出来RTO为40ms,由 于默认的 RTO是100ms,协议只有在100ms后才能检测到丢包,快速模式下为30ms,可 以手动更改该值: - ```cpp - kcp->rx_minrto = 10; - ``` + ```cpp + kcp->rx_minrto = 10; + ``` # 最佳实践 #### 内存分配器 @@ -143,9 +140,7 @@ TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的 默认KCP协议使用 malloc/free进行内存分配释放,如果应用层接管了内存分配,可以 用ikcp_allocator来设置新的内存分配器,注意要在一开始设置: - ```cpp - ikcp_allocator(my_new_malloc, my_new_free); - ``` + > ikcp_allocator(my_new_malloc, my_new_free); #### 前向纠错注意 @@ -169,3 +164,20 @@ 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%。 + + diff --git a/doc/donate.png b/doc/donate.png new file mode 100644 index 0000000000000000000000000000000000000000..2324ca26883ad11560509667303ea68c234fe94a GIT binary patch literal 5362 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 IvCF;x0_Z~>?EnA( literal 0 HcmV?d00001 diff --git a/ikcp.c b/ikcp.c index 7f4e8d7..cb03857 100644 --- a/ikcp.c +++ b/ikcp.c @@ -1042,7 +1042,9 @@ void ikcp_flush(ikcpcb *kcp) //--------------------------------------------------------------------- -// input update +// update state (call it repeatedly, every 10ms-100ms), or you can ask +// ikcp_check when to call it again (without ikcp_input/_send calling). +// 'current' - current timestamp in millisec. //--------------------------------------------------------------------- void ikcp_update(ikcpcb *kcp, IUINT32 current) { @@ -1074,13 +1076,12 @@ void ikcp_update(ikcpcb *kcp, IUINT32 current) //--------------------------------------------------------------------- // Determine when should you invoke ikcp_update: -// if there is no ikcp_input/_send calling, you can call ikcp_update -// after millisecs ikcp_check returns, instead of call update repeatly. -// It is important to reduce unnacessary ikcp_update calling. you can -// just call ikcp_update in a very small interval, or you can use it to -// schedule ikcp_update calling (eg. when you are implementing an epoll -// like mechanism, or optimize ikcp_update when handling massive kcp -// connections) +// returns when you should invoke ikcp_update in millisec, if there +// is no ikcp_input/_send calling. you can call ikcp_update in that +// time, instead of call update repeatly. +// Important to reduce unnacessary ikcp_update invoking. use it to +// schedule ikcp_update (eg. implementing an epoll-like mechanism, +// or optimize ikcp_update when handling massive kcp connections) //--------------------------------------------------------------------- IUINT32 ikcp_check(const ikcpcb *kcp, IUINT32 current) { diff --git a/ikcp.h b/ikcp.h index fda599f..9421b1c 100644 --- a/ikcp.h +++ b/ikcp.h @@ -342,18 +342,17 @@ int ikcp_recv(ikcpcb *kcp, char *buffer, int len); int ikcp_send(ikcpcb *kcp, const char *buffer, int len); // update state (call it repeatedly, every 10ms-100ms), or you can ask -// ikcp_check when to call it again (without low level packet input). -// 'current' - current timestamp in millisec +// ikcp_check when to call it again (without ikcp_input/_send calling). +// 'current' - current timestamp in millisec. void ikcp_update(ikcpcb *kcp, IUINT32 current); // Determine when should you invoke ikcp_update: -// if there is no ikcp_input/_send calling, you can call ikcp_update -// after millisecs ikcp_check returns, instead of call update repeatly. -// It is important to reduce unnacessary ikcp_update calling. you can -// just call ikcp_update in a very small interval, or you can use it to -// schedule ikcp_update calling (eg. when you are implementing an epoll -// like mechanism, or optimize ikcp_update when handling massive kcp -// connections) +// returns when you should invoke ikcp_update in millisec, if there +// is no ikcp_input/_send calling. you can call ikcp_update in that +// time, instead of call update repeatly. +// Important to reduce unnacessary ikcp_update invoking. use it to +// schedule ikcp_update (eg. implementing an epoll-like mechanism, +// or optimize ikcp_update when handling massive kcp connections) IUINT32 ikcp_check(const ikcpcb *kcp, IUINT32 current); // when you received a low level packet (eg. UDP packet), call it