1.說明:ui
[1]校驗和覆蓋的內容:spa
IP校驗和:IP首部。code
ICMP校驗和:ICMP首部+ICMP數據;blog
UDP、TCP校驗和:首部+數據+12個字節僞首部(源IP地址、目的IP地址、協議、TCP/UDP包長)。class
2.計算校驗和的步驟:二進制
[1]把校驗和字段設置爲0。數據
[2]把須要校驗的數據當作以16位爲單位的數字組成,依次進行二進制反碼求和。協議
[3]把獲得的結果存入校驗和字段中。static
另外UDP、TCP數據報的長度能夠爲奇數字節,由於計算時是16位爲單位,因此此時計算校驗和時須要在最後增長一個填充字節0(只是計算校驗和用,不發送出去)。di
3.接收端校驗校驗和步驟:
[1]把須要校驗的內容(包括校驗和字段)當作以16位爲單位的數字,依次進行二進制反碼求和,若是結果是0表示正確,不然表示錯誤。
4.二進制反碼求和步驟:
[1]二進制反碼求和,就是先把這兩個數取反,而後求和,若是最高位有進位,則向低位進1。
[2]另外,先取反後相加與先相加後取反,獲得的結果是同樣的。所以實現代碼都是先相加,最後再取反。
5.實現代碼:
static inline uint16_t check_sum(const uint16_t *buffer, int size) { unsigned long cksum = 0; //16位爲單位數字相加 while(size>1){ cksum += *buffer++; size -= sizeof(uint16_t); } //長度奇數狀況 if(size) cksum += *((unsigned char *)buffer); //高位有進位,進位到低位,下面兩行代碼保證了高16位爲0。 cksum = (cksum>>16) + (cksum&0xffff); cksum += (cksum>>16); //最後取反 return (uint16_t)(~cksum); }