一開始,私覺得校驗和只是簡單的求和獲得的結果,後來在TCP和UDP裏面看到使用的校驗和方式有點奇怪--二進制反碼(循環進位)求和。測試
人類的認知過程必將從簡單到複雜,看下這個二進制反碼循環求和是啥子意思。以16進制示例:spa
1.對校驗序列word1,word2...wordn的二進制表示求反碼code
2.對求的反碼序列循環進位求和,循環進位求和的意思是指把求和的進位加到低位,可能進位有x位,把這x位表示的數字和求和結果的16位相加。blog
感受好像變複雜了。不要緊,二進制反碼循環進位求和有如下特性:class
1.求和過程先求反碼再二進制循環進位求和等價於先二進制循環進位求和再對求和結果求反碼。(如此大大減小求反碼的次數)循環
2.與字節序(大端小端問題)無關。(這也許是許多協議使用這種方式求和的緣由)二進制
1 ///@func:To caculate the Checksum of data 2 ///@param: 1.nums :the number of sizeof(unsigned short int) 3 /// 4 unsigned short int WordCheckSum(const unsigned short int *data, unsigned short int nums) 5 { 6 short int index = 0; 7 unsigned int sum = 0; 8 unsigned short int checkSum ; 9 for (index = 0; index < nums;index++) 10 { 11 sum += data[index]; 12 } 13 //cout << "the sum of data is: " << hex << sum << endl; 14 checkSum = (unsigned short int)(sum & 0xffff)+(unsigned short int)(sum >> 16) ; 15 /*cout << "the checkSum of data is: " << checkSum << endl;*/ 16 return ~checkSum; 17 }
測試代碼:im
WORD data1[5] = { 0x1122, 0x1122, 0x1122, 0x1122, 0x1122 }; WORD data2[5] = { 0x2211, 0x2211, 0x2211, 0x2211, 0x2211 }; cout << "the CheckSum of data1 is: " << hex << WordCheckSum(data1, 5) << endl; cout << "the CheckSum of data2 is: " << hex << WordCheckSum(data2, 5) << endl;
測試結果:協議
可見,二進制反碼求和與字節序無關。margin