KCP

Note

[toc]

1. TCP協(xié)議

傳輸控制協(xié)議(TCP,Transmission Control Protocol)是為了在不可靠的互聯(lián)網(wǎng)絡(luò)上提供可靠的端到端字節(jié)流而專門設(shè)計的一個傳輸協(xié)議捏萍。是傳輸層的協(xié)議壳坪。

TCP是為流量設(shè)計的(每秒內(nèi)可以傳輸多少KB的數(shù)據(jù)),講究的是充分利用帶寬。而 KCP是為流速設(shè)計的(單個數(shù)據(jù)包從一端發(fā)送到一端需要多少時間),以10%-20%帶寬浪費的代價換取了比 TCP快30%-40%的傳輸速度肢执。TCP信道是一條流速很慢,但每秒流量很大的大運河译红,而KCP是水流湍急的小激流。

超時重傳機制

TCP協(xié)議要求:發(fā)送端每發(fā)送一個報文段兴溜,就會啟動一個定時器等待確認(rèn)接收信息侦厚。接收端收到報文段后就要返回確認(rèn)信息ACK。在定時器超時前數(shù)據(jù)沒被確認(rèn)拙徽,TCP就認(rèn)為“丟包”刨沦。接著會重傳這個包,直到接收端確認(rèn)為止膘怕。這也是TCP可靠性的來源想诅。

RTO RTT

重傳超時時間(RTO,Retransmission TimeOut)岛心,TCP使用自適應(yīng)算法動態(tài)調(diào)整RTO的值来破。
往返時延 (RTT,Round Trip Time)也就是數(shù)據(jù)包從發(fā)出去到收到對應(yīng) ACK 的時間忘古。RTT 是針對連接的徘禁,每一個連接都有各自獨立的 RTT。

TCP中對于RTO髓堪、RTT的控制算法有很多種送朱,但都比較極端,比如Karn/Partidge Algorithm的算法采用是若超時則直接將RTO翻倍干旁。如果還沒收到就再 * 2... 也有如Jacobson/ Karels算法驶沼,是一種加權(quán)平均的經(jīng)驗算法。但其中的參數(shù)確實有點神秘魔法含義争群,反正能用就行回怜。

快速重傳機制

發(fā)送端收到來自接收端的三個相同的ACK時就會觸發(fā)快速重傳,(其實就算報文沒丟失祭阀,也有可能因為報文到達(dá)的順序不一致導(dǎo)致ACK的重復(fù)發(fā)送鹉戚,而報文丟失必定會出現(xiàn)3個ACK鲜戒,分別來自N-1和后邊的兩個報文)。

普通的超時重傳太過笨重抹凳。丟失一個報文后就會重發(fā)之后的所有報文(為了確倍舨停可靠性而過分的慎重)。但快速重傳機制下赢底,發(fā)送端收到某個報文的三次ACK后就會立即重傳失都,而接收端會將之前收到的報文先緩存起來,然后在收到丟失的報文后幸冻,繼續(xù)正常工作粹庞。

延遲 ACK

接收端收到數(shù)據(jù)時要發(fā)送一個ACK(期待的下一個報文編號)表示確認(rèn)收到。但只發(fā)送確認(rèn)對帶寬有所浪費洽损,所以會延遲等待看是否有響應(yīng)數(shù)據(jù)需要發(fā)送庞溜,若有則附著其中發(fā)送回去。一般等待最多200ms左右碑定。這里的200ms指的是一個內(nèi)部的計時器流码,每隔200ms檢查有沒有ACK要發(fā)送。例如有一個數(shù)據(jù)段在185ms到達(dá)延刘,那么它最遲在200ms發(fā)送ACK漫试,而不是等待到385ms看沒有響應(yīng)數(shù)據(jù)再發(fā)送。(這對網(wǎng)絡(luò)延遲造成了更嚴(yán)重的影響)

ACK碘赖,UNA

ARQ響應(yīng)模型有兩種驾荣,即UNA(當(dāng)前未收到確認(rèn)信息的包編號,或理解成:此編號前所有包已收到普泡,如TCP)和ACK(該編號包已收到)播掷,光用UNA將導(dǎo)致全部重傳,光用ACK則丟失成本太高劫哼,二者取長補短會更好叮趴。

滑動窗口

一般來說,發(fā)送端的數(shù)據(jù)可以分為四類

  • Sent and Acknowledged:數(shù)據(jù)已發(fā)送权烧,且收到來自接收端的ACK眯亦。
  • Sent , But Not yet Acknowledged:數(shù)據(jù)已發(fā)送,但尚未收到來自接收端的ACK般码。
  • Not Sent, Recipient Ready to Receive:數(shù)據(jù)未發(fā)送妻率,且接收端已經(jīng)準(zhǔn)備好接收
  • Not Sent, Recipient Not Ready to Recieve: 數(shù)據(jù)未發(fā)送,且接收端也尚未準(zhǔn)備好接收板祝。
image

而所謂的滑動窗口宫静,就是指的一個動態(tài)的 發(fā)送/接收 隊列。如上圖,發(fā)送端的滑動窗口可以分為兩部分孤里,即發(fā)送窗口(已經(jīng)發(fā)送但未收到ACK)和可用窗口(接收端還能接收但發(fā)送端尚未發(fā)送)伏伯。

而接收端的滑動窗口也是類似的,其響應(yīng)的WIN值所表示的就是窗口大邪仆唷(剩余可以接收的大兴到痢),這樣發(fā)送端在收到后可以動態(tài)調(diào)整發(fā)送的數(shù)據(jù)大小虏等,甚至是暫停發(fā)送(讓接收端先把之前的數(shù)據(jù)消化掉)弄唧,以此達(dá)到流量控制,減少堵塞的目的霍衫。

2. KCP協(xié)議

KCP是一個純粹的ARQ協(xié)議候引,通過重傳機制實現(xiàn)UDP數(shù)據(jù)包的可靠傳輸,是一個在UDP之上SESSION之下的協(xié)議敦跌。以比 TCP 浪費 10%-20% 的帶寬的代價澄干,換取平均延遲降低 30%-40%,且最大延遲降低三倍的傳輸效果峰髓。是純算法實現(xiàn)傻寂,所以要自己定義下層數(shù)據(jù)包的收發(fā)方式。

KCP 提高流速

  • KCP啟動快速模式后RTO超時x1.5(實驗證明1.5這個值相對比較好)携兵,提高了傳輸速度。相較于TCP搂誉,若三次超時則變成RTO * 8徐紧。

  • KCP是選擇性重傳,只重傳真正丟失的數(shù)據(jù)包炭懊。KCP也有基本的超時重傳機制與快速重傳機制并级。KCP會直接重傳失序次數(shù)過多的報文,而非等待其超時侮腹。

假設(shè)發(fā)送方依次發(fā)送了 1, 2, 3, 4 號報文, 隨后收到 1, 3, 4 號 ACK. 收到 3 號 ACK 時, 我們知道 2 號 ACK 失序了一次, 收到 4 號 ACK 時, 我們知道 2 號失序了兩次. ACK 失序次數(shù)越多說明它丟包的概率越大嘲碧。

  • KCP的ACK是否延遲發(fā)送是可以調(diào)節(jié)的。KCP中除了單獨的ACK包之外父阻,其他所有包都包含有UNA信息愈涩。

KCP 報文結(jié)構(gòu)

KCP中共有四種報文,分別是

  • 數(shù)據(jù)報文 IKCP_CMD_PUSH
  • 確認(rèn)報文 IKCP_CMD_ACK
  • 窗口探測報文 IKCP_CMD_WASK
  • 窗口通知報文 IKCP_CMD_WINS

報文結(jié)構(gòu)如下:

0               4   5   6       8 (BYTE)
+---------------+---+---+-------+
|     conv      |cmd|frg|  wnd  |
+---------------+---+---+-------+   8
|     ts        |     sn        |
+---------------+---------------+  16
|     una       |     len       |
+---------------+---------------+  24
|                               |
|        DATA (optional)        |
|                               |
+-------------------------------+
  • cmd:域用來區(qū)分是具體哪種報文加矛。
  • conv:用來表示連接標(biāo)識履婉。
  • frg:其后報文數(shù)量。
  • wnd:剩余接收窗口大小斟览。
  • ts:時間戳毁腿。
  • sn:報文編號
  • una:尚未收到ACK的報文編號(小于una的都接收了)
  • len:數(shù)據(jù)長度
  • data:數(shù)據(jù)部分

利用ts計算出RTT(往返時間)從而判斷是否需要超時重傳。同時還有一個MSS(最大報文段大小)用來限制數(shù)據(jù)包的大小已烤,超過了就要切片成多個報文鸠窗。因此引入frg表示報文數(shù)量。

KCP 隊列與緩沖區(qū)

注意到struct IKCPCB里有四個struct IQUEUEHEAD胯究,是表示隊列稍计,也即發(fā)送隊列,接收隊列唐片,發(fā)送緩沖區(qū)丙猬,接收緩沖區(qū),都是手動實現(xiàn)的雙向循環(huán)鏈表费韭。且用大量的宏定義實現(xiàn)了隊列的相關(guān)操作茧球。這些隊列有一個初始的頭結(jié)點Head(不存數(shù)據(jù)),隨后可在頭尾進行插入刪除等操作星持。

https://luyuhuang.tech/2020/12/09/kcp.html

KCP 發(fā)送 接收 重傳

KCP 的整個發(fā)送, 接收與重傳的流程大體如下:

  • 調(diào)用 ikcp_send 發(fā)送數(shù)據(jù), 創(chuàng)建報文段實例, 加入 snd_queue 中.
  • ikcp_update 會在合適的時刻調(diào)用 ikcp_flush.
    • ikcp_flush 會做:
    • 發(fā)送 ACK 列表中所有的 ACK;
    • 檢查是否需要發(fā)送窗口探測和通知報文, 如果需要就發(fā)送相應(yīng)的報文;
    • 根據(jù)發(fā)送窗口大小, 將適量的報文段從 snd_queue 移入到 snd_buf 中;
    • 將 snd_buf 中滿足條件的報文段都發(fā)送出去. 這里的條件有:
    • 新加入 snd_buf 中, 從未發(fā)送過的報文直接發(fā)送出去;
    • 發(fā)送過的, 但是在 RTO 內(nèi)未收到 ACK 的報文, 需要重傳;
    • 發(fā)送過的, 但是 ACK 失序若干次的報文, 需要執(zhí)行快速重傳.
    • 根據(jù)丟包情況計算 ssthresh 和 cwnd.
    • 這樣, 剛才調(diào)用 ikcp_send 傳入的數(shù)據(jù)就在 ikcp_flush 中被發(fā)送出去了.
  • 報文到達(dá)對端.
  • ikcp_input 會被調(diào)用, 解析收到的數(shù)據(jù):
    • 所有的報文都有 una 字段, 根據(jù) una 將相應(yīng)的報文標(biāo)記為已送達(dá);
    • 如果是 ACK 報文, 就將相應(yīng)的報文標(biāo)記為已送達(dá);
    • 如果是數(shù)據(jù)報文, 就將它放入 rcv_buf, 然后將 rcv_buf 中順序正確的報文移入 rcv_queue; 接著將相關(guān)信息插入 ACK 列表, 在稍后的 ikcp_flush 調(diào)用中會發(fā)送相應(yīng)的 ACK;
    • 如果是窗口探測報文, 就標(biāo)記 "需要發(fā)送窗口通知". 在稍后的 ikcp_flush 調(diào)用中會發(fā)送窗口通知報文;
    • 包括窗口通知報文在內(nèi)的所有報文都有 wnd 字段, 據(jù)此更新 rmt_wnd;
    • 根據(jù) ACK 失序情況決定快速重傳;
    • 計算 cwnd.
  • 調(diào)用 ikcp_recv 接收數(shù)據(jù), 從 rcv_queue 中讀取數(shù)據(jù).

KCP 擁塞控制

與TCP相同抢埋,KCP也有擁塞窗口、慢啟動督暂、快速恢復(fù)等擁塞控制措施揪垄。

開始時cwnd=1,(congestion window,擁塞窗口逻翁,即發(fā)送端的一個可滑動窗口)饥努。每經(jīng)過一個RTT時間后就翻倍,但也不會無限指數(shù)增長八回。超過閾值后就是線性增長酷愧,這個階段叫擁塞避免,這個閾值叫做慢啟動閾值(ssthresh缠诅,Slow Start Threshold)溶浴。整個過程就叫慢啟動。

隨著cwnd的增大管引,網(wǎng)絡(luò)最終被填滿士败,就會出現(xiàn)丟包。此時說明cwnd應(yīng)該減小褥伴,即丟包退讓谅将。KCP對此的處理是:如果發(fā)生超時重傳, 就進入慢啟動(將ssthresh置為cwnd的一半,然后cwnd重新從1開始慢啟動); 如果發(fā)生快速重傳, 就進入快速恢復(fù)(將ssthresh置為cwnd的一半噩翠,cwnd設(shè)置比ssthresh略微大一點戏自,再以擁塞避免的方式線性增長).

[圖片上傳失敗...(image-4153eb-1628154473200)]

KCP 源碼

https://github.com/skywind3000/kcp

KCP的代碼是比較精煉的,只有ikcp.cikcp.h 兩個文件伤锚。

其中 ikcp.h 提供了結(jié)構(gòu)體定義擅笔,隊列操作志衣,接口函數(shù)聲明等。ikcp.c 是對各函數(shù)方法的具體實現(xiàn)猛们。

  • ikcp_create 創(chuàng)建一個KCP的實例念脯,將其中的各項成員初始化后返回該實例的指針。其中IUINT32 conv 參數(shù)用于標(biāo)識該KCP連接弯淘。通信雙方必須協(xié)商相同的conv才可以交流绿店。該連接發(fā)出的每個報文段都會帶上conv,同理也只接受包含conv的報文段庐橙。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末假勿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子态鳖,更是在濱河造成了極大的恐慌转培,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浆竭,死亡現(xiàn)場離奇詭異浸须,居然都是意外死亡,警方通過查閱死者的電腦和手機邦泄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門删窒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人顺囊,你說我怎么就攤上這事肌索。” “怎么了特碳?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵驶社,是天一觀的道長。 經(jīng)常有香客問我测萎,道長,這世上最難降的妖魔是什么届巩? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任硅瞧,我火速辦了婚禮,結(jié)果婚禮上恕汇,老公的妹妹穿的比我還像新娘腕唧。我一直安慰自己,他們只是感情好瘾英,可當(dāng)我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布枣接。 她就那樣靜靜地躺著,像睡著了一般缺谴。 火紅的嫁衣襯著肌膚如雪但惶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天,我揣著相機與錄音膀曾,去河邊找鬼县爬。 笑死,一個胖子當(dāng)著我的面吹牛添谊,可吹牛的內(nèi)容都是我干的财喳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼斩狱,長吁一口氣:“原來是場噩夢啊……” “哼耳高!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起所踊,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤泌枪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后污筷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體工闺,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年瓣蛀,在試婚紗的時候發(fā)現(xiàn)自己被綠了陆蟆。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡惋增,死狀恐怖叠殷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情诈皿,我是刑警寧澤林束,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站稽亏,受9級特大地震影響壶冒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜截歉,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一胖腾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瘪松,春花似錦咸作、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至壳嚎,卻和暖如春桐智,著一層夾襖步出監(jiān)牢的瞬間末早,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工酵使, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留荐吉,地道東北人。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓口渔,卻偏偏與公主長得像样屠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子缺脉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容

  • KCP介紹 1 簡介 KCP是一個快速可靠協(xié)議痪欲,能以比 TCP浪費10%-20%的帶寬的代價,換取平均延遲降低 3...
    hexg1016閱讀 19,065評論 2 4
  • 第5章 運輸層 5.1 運輸層協(xié)議概述 5.1.1 進程之間的通信 從通信和信息處理的角度看攻礼,運輸層向它上面的應(yīng)用...
    轆轤鹿鹿閱讀 894評論 0 1
  • 一业踢、基本慨念:IP地址 =網(wǎng)絡(luò)號+主機號.域名系統(tǒng):是一個分布數(shù)據(jù)庫,它提供將主機名(就是網(wǎng)址啦)轉(zhuǎn)換成IP地址的...
    JoeJiang閱讀 477評論 2 8
  • 套接字選項SO_RESUEADDR 即使端口處于2MSL狀態(tài)礁扮,使用該選項知举,仍然能夠在該端口建立連接。服務(wù)器常會設(shè)置...
    Myth52125閱讀 1,409評論 0 0
  • Catalog HTTP 協(xié)議1.1 特性1.2 HTTP 報文1.3 會話1.4 緩存1.5 缺點1.6 HTT...
    是ADI呀閱讀 544評論 0 1