最近加入了一個用幀同步的項目,幀同步方案對網絡有着極大的影響,於是采用了RUDP(可靠UDP),那么為什么要摒棄TCP,而費盡心思去采用UDP呢?要搞明白這個問題,首先要了解TCP和UDP的區別 , 明白TCP無法避免的痛點。
TCP VS UDP
1.Tcp 面向連接,提供可靠的傳輸; UDP面向無連接,提供不可靠傳輸
2. Tcp 提供流量控制 ; UDP不提供流量控制
3. Tcp 保證傳輸數據順序 ; UDP不保證傳輸順序,也就是可能是亂序收包
4. TCP 面向字節流 ; UDP 面向數據包
……
簡單說TCP保證了傳輸的准確性和相應的流量控制,而UDP不提供任何准確性保證。既然TCP提供這么多完備的方案,為什么還要大費周章地去設計RUDP呢,這里主要願意可以用兩個字概括“速度”,TCP提供了過多的保護,在及時性上做了很多的妥協,比如:控制微包(Nagle算法),延時ACK,流量控制,超時重傳等,這些設計嚴重影響了Tcp的速度和及時性。更多的信息參考鏈接:http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/
幀同步中的UDP
幀同步方案中邏輯幀一般都在8~16幀左右,一般都在12幀以上,這要的網絡傳輸頻率決定了不可能采用TCP協議,那么如果采用UDP會出現什么問題呢?
1. 丟包,幀同步中邏輯幀在每個Client上一定是一致的,也就是說決定不能出現丟幀的情況,
2. 數據完整性,UDP協議頭部雖然有16位的校驗和,但是IPv4並不強制執行,也就是說UDP無法抱枕數據的完整性
3. 亂序。 UDP並不保證數據的順序,故可能出現數據包亂序問題
以上問題任何一項都會導致Client在邏輯幀上出現不同步問題,為了解決這個問題就必須引入RUDP概念,這里的RUDP主要是解決上述的問題,並不某個RFC定義的規范。
RUDP初步
簡單思路,既然原生UDP有那么多痛點,那我能不能像應用層協議一樣在UDP數據包頭再加一段包頭,從而定義為RUDP呢,答案是肯定的。首先思考RUDP需要解決哪些問題,然后根據問題加上必要的包頭字段。
1. 數據完整性 –> 加上一個16或者32位的CRC驗證字段
2. 亂序 –> 加上一個數據包序列號SEQ
3. 丟包 –> 需要確認和重傳機制,就是和Tcp類似的Ack機制
在思考一下既然是自定義協議是不是需要一個協議號字段來過濾一些非法包,那么又可以加入一個新字段:
4. 協議字段 –> protol 字段,標識當前使用協議
綜合以上字段,我們的RUDP就可以簡單實現成如下:
根據初步得到的協議頭,就可以嘗試去實現協議啦,后面會開始一步一步實現整個RUDP邏輯。