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
zcmaJ_XIK;6)}16k0Hqfd6#^=tpnxcyP((#(7EtM6D2jw8p@oDXN>f2D3MwT^6OfJ+
zX+f!iR6$AzK@<rj7-~W&;fv3`-uJ#=`!UbVGjnF2wbwrToV9n{CCl>y{8Ib?00>+#
zHMs%+AkHHQ;N{`m90Kw^06_fx1rsCdkn{yogx`T-SLh<WUe_$e`<t_!>zC<}^~-!K
zEk3-m_aj~Er=F5~_P!iEOfk=Yp%KZWsLuB;^4*gQpYC5!xP1nqlWXC!o}`gmZjUv`
zrO3$3M^3e>S*$-ZFI()YK$xY350a=dgK_n1q=hE5FVlyKF;JH_t0OUkkPE@gM$D$h
zp<FJJv7=vT0<f%~u7I%ZBaoq+8V``vwihswMEq|rif)5cCscf%fP=xpJ>xuClCa!n
z3w_9PcTc|FAmFDN-)B562<Xw`^7v%^-=s+d_l8GQCMO4**n}Pim7%l!9+(7+qeR*!
z7JRNvoZyZ|^W=yHxxePY5mnfd;F?7@tDJMDf%UesvVQgIFkim6nf+iFkMD7&F|9qE
zKWIPP6wfCw0i)<DEq5<|12xAJNj(!qPfk7<)@NSK?noH`{3@rhfXr!Ic@Yb-vkf$l
zHi)IAly3VYZd{s#E@<`TvBcQI4TPrBHC^p7&n(qLzx|Pp>DO782?$sY5F;87%?BYx
zGhXOra+lS8kP8d;Y!lPhW<l$SSqFhbw*DpJmnMZ}m&$(`u?~_p;-)>uNXsxBSp{Q|
zE@5Trl5ue#_=aY{GcDhx#$~k(<iIW*(WDSiL^eNdF6id@kytf<<l>WGFVx?sNsys_
zM*VC2XZ7NVCQ|s+wsX|4`~cHJ{N4#AT+**}hpekIm;a%y9V)AOcb7hl^Wnf_|0)3}
z$B_@d=Xt~H(1zIJfx1}l=^r_Jd*em;l=&+f(j-c?v_mf*Ld`jVxC$?sHk9frMC4o+
zN<!7$4Om({SAOPVy0FVq^8VsCuL0h$I61D8sSj2|&wqj55B9{9!CD`EZ8eqL4rOz<
zpd}5bQ%TyP5w~W<Y@0uQ;y#7}7e0kF_rz}-rQGG2S(;BfW8!3K84r`4@@UIXPF}I;
z^7+C4s@oUzMqousF*VlfNwX05A{O8FG_l_ACGZ7uFt+naX1bpKqdeRdpw?FHXU*rm
z{URI6JSLK&&4PSIMKzDoB%m4TwB2@j^Ab4U4@v<6#^vU6{I7HstakfJ^uNB6Hz(h$
z8{K^<OL(6EuHcN;C$~_OAF^t@U45_?*`P8ST-&=sPj1=t+d0$SFOQw@18TRYJ$jeU
z4>|PWwo=k0qSjLUHRJ8mL9Ae-uB-3Cwbrh-a$cgc{zrip5Nxsjv5&CG+4JD@P{$NH
z&*6%_5M1ZY-GJOfH6T{G9f1A)g(MLWmTL$dEKI5h_}G?DWiI<9rp_~13wUQt-PZh7
zQl`faw)Lzx1Q)yd$H0x7;O4;n<~0Jv_INLRluz3An#ahnP!&=HnKSrZVJjCPQt&7F
z%3FC1hmawp4U1GVZS#jK^8$r&^wcIZ+vcza5Zfv97dojQBl3@k7=Jp0QvJ=Q+sbQy
z{qUbD|LFuSmNGdaxXB6`_7n=-)cT06j=cA`tQXx6^klYJqR?5=&{y`@%2|l2zU7B&
zaRPwca>pOn<M?pb>V1pQWP|xWn;K`Ew~fKLyd&~Jtm(l&VA?bQy9Id3oCazX>7(-H
z?m7!2&8UsLwz+-FrkrDJ@GoNm04bD=A{ONlTV2T=8u~HLL)~vrI$|9*4{*?!{7C$>
zBi-a+^AStK!bz)aO7EO!9h@-JlKG{7wUXB#xq{|Q8Eg7)HaKuTX1;;X&or7R=8hmC
z=Se?D7VfHHoDGiBHO$Qc;Ut|uyPTOha0)G`ODbP+s_Uc2Y)gYl8jW-QKwgLIbLrWE
zLQyfmBq!lNP!uBlR7kUH7UU78JvmV3{@f-7yLK9#9z6$-&spVb{qI1`Yd|g7k<4RX
zILWidQgd`3>Jw~5DHBTm9_LXW+%Jr0X+C+^R87<MQH*$@xdD2B#suHjk8yb$kK|y6
z^B7W-0oaVIf*yU}g|!vKwXa+KZ<<cVX<e0<_{}|s+b>8L5}eD%h*&F-{vIJq3uR?v
z6VEtoa&h=G$w>qWN1O#hfxCxFm{aB%1+mm4QF{S34LCd@E-vn=@XZqduNp?;*!}0*
zbz8GDU1^fJrEj+#sp>!m&_6a7*V}7}*fbfa;LwYOJEwYuW@l%2&aMa>TOat0C8zER
zo4UT)Abt#iKxl<5!s_blZ8QjTba&Nlnu&w07;vG&mkbwwcov{bKN{{`pCm*n8q}IW
z!>fdsu+^MT$_}+<AM~?4T!Gd^WpREmZ;%UAf4$M-o*nu6ZO)0h%+gaO$$WrE?&Xa5
z+}heI`#Es^8NL{FfPrdM!VT7OjOL>5ojTGrA|oSXFgh@x=IptnXjd+PE9+>F*$xlO
zZf|cFq%N)u*{@A8PmI*he~zastbAW@v#NRKTe@8RI3b~zPN6LNSl!k;lS4l_l+kjj
zs-c!c|LAA5Uy97cWMxqCTH-JLs%g(nChcY85K{wmk!nrdn-hWn4x3j+HI3VVMVf)w
z445a`>pIut1FMrtU?<RFtD9g$CJRGawm!SPg)Q!FDtpFIn%9=PgFIinW<#}#Z{@-r
z-|B6;`}6aMm=oKTb?!M=j^?N%B@EIC`B19HRw!vLZ&_@e4sGgH!f|m3Fn<D}w{;M{
z*MHu($H8U^bL?6Bu0)}YlA1dsC&=!Ka86*q?*Ulh(#grmfL9`S{<U_te!c3+lUFJm
zofl@sBRH8{Mkk)vFU5{+M0zrg%1Am)PL?wDaKYPl5nTpMVnW!agmooxqK;tYpY$9k
zv#5fUZ7D}A-@fBjLL95&HA~RRoA!KB{r(1OqwXbjYcZmFs5osp4kWCeTj|&Mt<gBP
zg=b@Zj%IhiSBJW|Z194E=_<8A50FUR-eDE142N4bZ@#jcqYvUAmNxJe1m=0a$QsLd
zl_Ej}R7pRXn-hU)s+1K<m0$=Rkn!ClOhy?GcOBiS-<pErlr)P<L$+#@wpY=UPHSXM
z+9ta?mJ_HhBA24UVmE>3m<(58@XRG_Xhi$CSsCqlvQkRp;)HrA-Qe|a91Hxfwwh_{
z1I5obSA4%7KSU-bE`1@~sA_04yB;#Hv^-^{%47I>s1AH%y%U-wy?t6f8W*QSeKQ_e
zeH}W$n4hBcF?>R}D==#E^78$YV>abmLegv<hY@$+ur+6oU&Yvx`~g>zX35w6gvIxF
zF0Bujs=a`^+3#U^uS)}QH?d$vNdQ=hV5m^S*Xk9e!Sd00-CdvY>`KbFs{jC%{{oa0
z<@+*!k?f!m#VjBzGio3ZfB8x~_hEU!`zrPb%sE^<SO&ER9yTUp#2d+Y;ohaoUM4B2
z26fq}QzZvh79Tv9;?6tw#=zH}E3j(MVw8{o0I=D^m5Zst$Pb;;nq8!<ST*2gJDR&}
z^#h{6e#TmF+d1{s4dt)2bu*N*A-V(Hc@uOsyTxy3^(f~_pJ^q;{zS*rB)m6^ObgrD
zvwm(*3RtUbS?5tngGL1=hobu18kv0$n$TALMib%fT{OKi-nX+WXI9tLEbilLwMX6?
z`+6IHd=L31<b3X&IeA{`w8;2D!<@*HgU)A15=y~9{N04+{x$=6!w|0JaX}Tw*({$!
z^VNJ3<IOgBZbj~9b{oAT5&~^-mkCn6mT@?zSj;oMQM#i<XaAlZvKP>tG8s8GBiQ4x
z{ZPDrQhgic6=0CC@yoxmn^rf)-TB^Ze&J#Pws>=~N17=zqS1usq+an!<U+0IB0Rie
zCw>fXQ_r6t6vS?Aw+QL$5(3=2w|~w%!yNav3`P#qOYGB|j+yp=#`QWjDtg}ZVH@f1
zR3IG_uNtky4{}zFIRArqEbeAGuE(k=mYwKWV%-bvvrYVdE#tBISSw73v~re4UJ;ZR
zvY4t$)JrHh^PNHpU!u*neX96rqzTg_=<li_@fLA1oDTx?kXKMp0#C(33DIj2%lnG-
zcTVbU$S_$Y5nsoJ5Cciw1Dlg52~YN{Ci&q4u?7OTg$W)W#F-*GVs-?ch$_jDaLZpi
zUw;ekPOl&O+;n-Ba}LxoT`g*~w>P-9hK}{2=isML+lT<AjSMO2t)B;Lx90o4#ozI1
zCzkql6ee3XJ3B@kPdTA4s<PvzTT;)Ke-|9|ft7(62p->v&-=jF(FoP_8ONnMg%vae
zx&1tD;xTF5`B7Z(;NEttJ`69e_1^1Qzg0&4vFd_A8`z-Xj6KL}hwz-uv_`hnbfKkR
z9<K(uyfuD(X~`wwspuI3OCpmTuF_jOb!=-AJu>Z59!p?#5iAqMOmqFGp}nPA#8f>3
z%gLKqjbsQKAAi9jb$*7zjtB;!5Sta1uw{hSTtVV>WrbbsLCJC-f!G(zaNM#|WU+nC
zG~Q?Dl%;JIzo*ms1-J2^*Bo~$9)A6{ai^sDYq5Pfih6BLp!4%t;zxG?hmZJiTNyjE
zUu!v)so7vK<ggp}{HP<ydcUZij!yh+CPp$CtMTxNS<2M<_r&w^$&pV*eH)f|Cb64H
zpjo|758-Bi-xSeTNNDbyx8kIx7#mZZ6mV20j&njIdRnB@oMu<z!%~jhYp}oC`=UZh
zfd&lsnKNhhN=Xflwbpf=Kaj$v?F_wzN`f6vr})mNKg3dFNHP6|98q+kDx9^<7;%nh
z^iqd;%|Hpl;O<lv{K!***U@Ugw8D{GJ#Rh3A=#-$aHrcz;7NSoA=CX3SoGH-+o%p{
zbWy=|&}8L~_H4S??QOSn-VnoJ%i1zJgvt;Zl7e0em<*kD?M^vfc^$l#a=LhnhPQm<
z&t}bz*jK-10aBxRmxAF(k=W8v9^iH0ltl2a3GM2;v%MvQ>$tMqD@Rw?)(%pr)HJ9Q
zqeBV;V_(5wFpiw-@`!y^4SxCoM@W@(q|Q7BP4eW<YNDr~%A>EmW$#=?{Yx0$@~_Hc
z@NdS;&nG1f9r!K0InvI&k63EgGzSOS<Pn?m@O?sPK?B0ZR+*5i-QT6PHv~r0a37^7
z3!&j4(gq4oPTbH33JF4avw@G^axja`{iUqA42PI&**=G&^)=u$IB0lb$-Zgq(Ej9Q
z<?}bexY(gT>X{?h4Qnjsa&@g5yh3}VgI{gXUBe<iVy&Wz>Fkx{=KxF&^`}Be83k@J
zZfus(&8XG4TblYvUWhfD&A`C!hYwphv$Ou1oyTw#={CG!JtDM8dXPsf@<&%22V)~^
zt67czL;1Rr-}o{{Lx%gd-)*dH)Ma5+fDVxGW!k?HdP81~-CeF4uLRevv4&+B>Gz!S
z$lJFz$hsx}jMd-$9z_sQ4={MWd8S-`N@>?>dSu~02HTnc!xdgMt=@;_TEjv;ASno=
zWMc6ieb51A&MN+of?zjr#yqh~Q~$inDB?ScsX+6TG4BJt5dTBTKZ_>V;mb9zQTWmk
zWF<9WSd(;aBm)nlc?#HZ|EU^&JM){qs!&RH=66mN5;!t~RHridDA-<qz{Ks~e@gax
zfj7i+zCkiZ6V>EZH1|IOoSkj{9yAUm!{gq0<l#Mx`W-tY+73Apef(c4`2Xv2T;;=I
zfRyMeSrfPDboez0-vQu?OXU;F9q;5=MPss1oy!!^`D5w9#{(1nqYU9BK6K@@GQs_1
za_#Y3p^*@mrJ5P6CRIIsLnG<qth?H+7bZC#7jFXam~Yd*-P=ap>f?M`Tk_Sx5QUe@
z$+2C$2RtjZvO%!OXY!ny*6%1cj%yiwYu6n_Y<~5(qID-+o4iezH9s!%z|T6{A>{Y^
z?VE%9p5C?YIwBV#THEToPa!7g*-42s;L68RsIi})NYd>V+ocCCW*2im-Po^v;~{Wm
zP13K@SVz0J+1M?fi>)(y(~DEYfBN(;Z4JL18cbNf*!QZzsVZEqQ2a*-1W-_*W<Gz*
zw-DgS8~$_6V!9gfD}^BNRxm5)Zsl~6YPYW<kZzPS!QRM-1p1$Kz<HDIS>H(&7U8r2
zP{0ZPiX!z`@ql^MsUU7x?tOB8^FAMgc!X{Ft+SRqSi{K9AP%}dphU32I7(qGIt}2o
z4_+aYLz|syoVTLX6-)2DgUi`-Is^PJPW>||or$UqU|gq6%OD}iaMvyesz+N@gRY@9
zY0)O@x@7rP_YB6V6v|M61h9*J`4>tvUO~28o}#0EU4UCbLE8z(+kEL-ktxJCzeIs6
zQ*T;&AC1c)ieW_A-C1Rn26pfAJ@PBC-A`2dDK`lz8~@M|FHG;wSrW&E&hd0pq@UbD
z)wFcl-pDn06%P-V&bt?MO!SCR-as}sx*+dedADDWFf0pa&dA<}jOn}IoDKA<+nx{s
z0n)(%gOqajhC{udKCPiO<G8P~ro_ZVFJlmfiiq3Bb8*h6^tVziz;clEba6{l_n0uH
z-cJ`mvL;VlTTHA!?K7dYP+ACkRB{77<VE}{vv|pT+_6RSp7{AYF5ZMfQ|R}n1|_w+
zN`n4jYFTpyjIe+!x8-H7zSNNFt8dXgu?K0X;KS`F!WH(i(#GUllBkbV$d8PuTGUL`
zNiuB#WJe+4)OTR`G}f7?H|(OA0(V{juq?`-&E)^?cx)RGi04*%<<Q)mUM6titffhb
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