概述 KCP協議結合了TCP和UDP協議的特點,是一個快速可靠的協議。 引述官方介紹: KCP是一個快速可靠協議,能以比 TCP浪費10%-20%的帶寬的代價,換取平均延遲降低 30%-40%,且最大延遲降低三倍的傳輸效果。純演算法實現,並不負責底層協議(如UDP)的收發,需要使用者自己定義下層數據的 ...
概述
KCP協議結合了TCP和UDP協議的特點,是一個快速可靠的協議。
引述官方介紹:
KCP是一個快速可靠協議,能以比 TCP浪費10%-20%的帶寬的代價,換取平均延遲降低 30%-40%,且最大延遲降低三倍的傳輸效果。純演算法實現,並不負責底層協議(如UDP)的收發,需要使用者自己定義下層數據的發送方式,以 callback的方式提供給 KCP。連時鐘都需要外部傳遞進來,內部不會有任何一次系統調用。
TCP是為流量設計的(每秒內可以傳輸多少KB的數據),講究的是充分利用帶寬。而 KCP是為流速設計的(單個數據從一端發送到一端需要多少時間),以10%-20%帶寬浪費的代價換取了比 TCP快30%-40%的傳輸速度。
傳統的TCP/UDP協議見參考鏈接。
協議格式
| 4bit conv | 1bit cmd | 1bit frg | 2bit wnd |
| 4bit ts | 4bit sn |
| 4bit una | 4bit len |
| anybit 數據 |
- conv:會話序號,通信雙方一致
- cmd:報文類型
- IKCP_CMD_ACK 確認
- IKCP_CMD_PUSH 數據推送
- IKCP_CMD_WASK 接收視窗查詢大小
- IKCP_CMD_WINS 接收視窗大小告知
- wnd: 己方可用接收視窗大小,接收視窗大小 - 接收隊列大小
- frg:包分片(數量)
- sn: 包分片序號
- ts: 時間戳,用於計算RTO和RTT
- una:待接收的序列號(確認號),表示該序列號之前的所有報文都收到了,可以刪除
- len:用戶數據長度
- 數據:用戶數據
特點
RTO不翻倍
RTO(Retransmission-TimeOut)即重傳超時時間,TCP和KCP是基於ARQ協議實現的可靠性,但TCP的超時計算是RTO2,而KCP的超時計算是RTO1.5,也就是說假如連續丟包3次,TCP是RTO8,而KCP則是RTO3.375,意味著可以更快地重新傳輸數據。
選擇性重傳
tcp 丟包時會全部重傳從該包開始以後的數據,而 kcp 選擇性重傳,只重傳真正丟失的數據包。
快速重傳
收到fastresend(配置)個失序報文後,不等待超時,直接重傳,減少丟包等待時間。
而TCP重傳模式:
- 超時重傳:超過規定的時間 RTO 則重傳
- 快速重傳:收到三個冗餘ACK,不去等待 RTO ,直接重傳
與TCP相同,都是通過累計確認實現的,發送端發送了1,2,3,4,5幾個包,然後收到遠端的ACK:1,3,4,5,當收到ACK = 3時,KCP知道2被跳過1次,收到ACK = 4時,知道2被跳過了2次,此時可以認為2號丟失,不用等超時,直接重傳2號包,大大改善了丟包時的傳輸速度。
非延遲 ACK
停等ARQ協議
- A會為每個即將發送的數據編號,編號的目的是為了標識數據和給數據排序
- A發送完數據之後,會給這次發送的數據設置一個超時計時器
- B收到數據,將會返回一個確認,該確認也有自己的編號
- A收到確認,將刪除副本且取消超時計時器,保留副本的原因是傳輸可能出錯
- B收到錯誤的數據,或者數據在傳輸過程中出錯,總之就是說B沒有收到想要的數據
- A在超時計時器的設置時間內沒有收到確認,此時重發數據
所以可靠的TCP有32位序列號和32位確認號,TCP和UDP都有16位校驗和。
連續ARQ協議
連續ARQ協議不會響應每個數據段,而是僅僅響應編號最大的這個數據段,表示之前的數據都收到了,這個叫做UNA模式,而停等ARQ協議可以看作是ACK模式
ACK + UNA
ARQ (自動重傳請求,Automatic Repeat-reQuest)模型響應有兩種方式:
- UNA:此編號前所有包已收到
- ACK:該編號包已收到
只用 UNA 將導致全部重傳,只用 ACK 則丟失成本太高,以往協議都是二選其一。而 kcp 協議中,除去單獨的 ACK 包(精確)外,所有包都有 UNA 信息
非退讓流控
KCP正常模式同TCP一樣使用公平退讓法則,即發送視窗大小由:發送緩存大小、接收端剩餘接收緩存大小、丟包退讓、慢啟動這四要素決定,慢啟動是在剛開始發送數據時讓視窗緩慢擴張,退半避讓是在網路擁堵時視窗大小減半,快重傳是在網路恢復時及時給予響應,與之配合的就是快恢復。但傳送及時性要求很高的小數據時,可選擇僅用前兩項來控制發送頻率。以犧牲部分公平性及帶寬利用率之代價,換取了流暢傳輸的效果。KCP 實時性好,但帶寬利用率較低,因為:
- 非退讓流控,不斷嘗試發送數據,有效包不多
- 每個包應答,占用一定的帶寬
視窗協議中有兩種:
- 擁塞視窗:防止過多的數據註入到網路中,這樣可以使網路中的路由器 和鏈路不至於過載。
- 滑動視窗:接收方告知發送方自己可以接收緩衝區的大小,通常與連續ARQ協議配合使用。
結構
大概流程如圖示,若是想深入探索底層實現,請參考源碼或者參考鏈接中的詳解