理解UDP協議的首部校驗和校驗和


reference:

            https://blog.csdn.net/qiuchangyong/article/details/79945630

            https://seanwangjs.github.io/2017/10/19/udp-protocol-checksum.html

 

關於udp傳輸的不可靠性,用過這個的人都知道會丟包。具體細節可能就不清楚了,經過我的理解和總結,有以下兩點:

1)udp包的大小可以達到64k,但實際上mtu大小只有1k多,如果直接發一個超過mtu大小的包,就會在協議層被分片,這樣的問題是,如果只要有一個分片在傳輸中出錯了即校驗不正確(這是較容易發生的),整個傳輸的udp包就被丟棄。注意是整個而不是單個分片。這就是為什么發送udp包通常也是1k多大小的原因,rtp是在udp之上的協議,也考慮了這個問題。

2)實際上收到的數據都是經過校驗的,不存在傳錯的問題,即在應用層調用udp傳輸時,不會出現發送了"ABCD",收到的卻是"ABED"的情況,只有丟包或亂序的問題。而udp接收緩沖區過小也是造成丟包的原因,適當增大udp緩沖區能夠降低丟包率。

在實際應用中,比如流媒體傳輸中,就要對接收的亂序的包進行重排(重排時間的長短又是一個關鍵),這時候發現某個包丟了(前提是要加一個序號,這個rtp包頭里面有),還需要做重傳的工作,然而udp協議就是為了傳輸的實時性而生的,所以這里面就有一個權衡的問題,既不能全部都重傳,也不能不重傳。如果全部都重傳,那就和TCP沒有區別了;如果不重傳,丟包就會導致流媒體的不完整性,需要做的處理就是錯誤修復或隱藏,對於音頻和視頻都有一些算法,由於信息丟失,這些算法也只能做一些彌補,但對於無法進行重傳的情況,比如播放基於udp的ts節目流,這些糾錯算法的好壞就是關鍵。

 

45 00 00 2e----4表示ip版本號為ip第4版;5表示首部長度為5個32 bit字長,即為20字節;00 2e表示ip總長度為46字節,其中ip數據部分為26字節。 
be 55 00 00----be 55表示標識符;00 00表示3 bit標志及13 bit片偏移量; 
7a 11 51 ac----7a表示ttl值為122;11表示協議號為17的udp協議;51 ac表示16 bit首部檢驗和值; 
de b7 7e e3----表示32 bit 源ip地址為222.183.126.227 
c0 a8 12 7a----表示32 bit 目的ip地址為192.168.18.122

-------------------------------------------------------------------------------------------

檢驗和計算: 
首先,把檢驗和字段置為0。 
45 00 00 2e 
be 55 00 00 
7a 11 00 00<----檢驗和置為0 
de b7 7e e3 
c0 a8 12 7a 
其次,對整個首部中的每個16 bit進行二進制反碼求和,求和值為0x3_ae50,然后3+ae50=0xae53(這是根據源代碼中算法 cksum = (cksum >> 16) + (cksum & 0xffff) 進行的 ) 
最后,ae53+51ac=ffff。因此判斷ip首部在傳輸過程中沒有發生任何差錯。

"二進制反碼求和" 等價於 "二進制求和再取反"
從源代碼看,很關鍵的一點是二進制求出的和如果大於16位時所做的操作,用和值中高16位加上低16位的值作為最終的和值,然后再做取反運算.


 

對於TCP和UDP的數據報,其頭部也包含16位的校驗和,校驗算法與IPv4分組頭完全一致,但參與校驗的數據不同。這時校驗和不僅包含整個TCP/UDP數據報,還覆蓋了一個虛頭部。虛頭部的定義如下:

 

                     0         7 8   15 16   23 24       31 
                    +--------+--------+--------+------------+
                    |             source address              |
                       +--------+--------+--------+---------+
                    |           destination address          |
                    +--------+--------+--------+------------+
                    |  zero  |protocol| TCP/UDP length  |
                    +--------+--------+--------+------------+

其中有IP源地址,IP目的地址,協議號(TCP:6/UDP:17)及TCP或UDP數據報的總長度(頭部+數據)。將虛頭部加入校驗的目的,是為了再次核對數據報是否到達正確的目的地,並防止IP欺騙攻擊(spoofing)。

 

以及這段信息的十六進制表示

有了以上這些內容,剩下的就是對照着最開始的圖表來尋找各個參數的值了( wireshark 一個十分好用的功能就是點選上面的人類可讀內容,其十六進制值會在下面高亮顯示)。我用下表來表示

key human hex
Source 192.168.1.106 c0a8 016a
Destination 11.111.111.111 0b6f 6f6f
Protocol UDP(17) 11
Length 17 11
Source Port 63549 f83d
Destination Port 12345 3039
Length 17 11
Checksum 0xb12d b12d
Data hello UDP 6865 6c6c 6f20 5544 5000

然后就可以開始着手校驗和的計算了,但在這之前還應注意,上表中有一項 Checksum ,這是發送方根據發送內容計算出來校驗和,接受方需要根據收到的內容重新計算一遍校驗和,然后再對比兩者。所以在接收方計算時應該忽略這里 Checksum 項。

再次舉例:

source ip

destination ip

protocol udp :固定為0x11

length*2 : length為:數據長度+8;

source port

destination port

data:從開頭取16bit,當結尾為8bit,將低8bit設為0x00;當然0x00不能算為數據長度

上述計算完成后,將超過16bit的高位截取,加到低16bit中;再取反,即0xFFFF減去其即可。


C0A8_0003
C0A8_000A
11
10 (8+8)
10
8000
8000
1122_3344_5566_7788
----------------------
3_92E2
-------
92E5
------
6D1A


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM