3月份開始從客戶端轉后台,算是幸運的進入全棧工程師的修煉階段。這段時間一邊是老項目的客戶端加服務器兩邊的維護和交接,一邊是新項目加加加班趕工,期間最長經歷了連續工作三天只睡了四五個小時的煎熬,人生也算是完整了。。。寫博客也算是又一次廢了。。。
一邊趕項目,一邊看TCP/IP相關的書,本科學的網絡知識一直都是一知半解,現在終於有機會深入研究一下了。
TCP/IP主要就是各種協議,各種接口。校驗這個概念,一直都不陌生。之前在客戶端用的最多的校驗是MD5、CRC校驗,在邏輯層網絡協議,客戶端文件等用的比較多。但是一直沒有深究里面的原理。而網絡傳輸用的就更多了,IP頭、ICMP、TCP和UDP 都用了反碼求和校驗。
-------------------------分割線--------------------------
CRC校驗:
設原始信息字段K位,校驗字段R位,碼字(最終發送信息)長度(N=K+R),則對於CRC碼集中的任一碼字,存在且僅存在一個R次多項式g(x),使得
v(x) = a(x)g(x) = m(x) xR + r(x)
其中m(x)是K次多項式,r(x)為R-1次校驗多項式,v(x)為CRC碼
也即二進制m(原始信息)左移R位,加上剩下的R位(余數),得到值v(最終發送信息),能被一個選定的二進制數g整除。發送端發送的信息,到接收端能被指定的數g整除,則信息是完整的。為了唯一性,g(x)一般會找一個特別的素數,因此有CRC16,CRC32,有相應的標准。
發送端:有m,g,R,需要求r,然后組合成最終信息v = m*2R + r。
接收端:有v,g,計算v % g == 0則正確。
那么r怎么求呢?一般概念介紹只說用m左移R位后除以g,余數就是r。
比如輸入1001,校驗多項式11001,采用多項式除法
10010000
11001
------------
01011000
11001
------------
0111100
11001
------------
001110
最終發送碼為10011110
可是 10010000%11001 = 1110 只能說明m*2R - r能夠被g整除,那為什么m*2R + r也能被g整除呢?答案在除法方式上,這里用的除法是模2除。我們可以看到CRC校驗在除法過程中用的是亦或操作,
0-0=0,1-0=1,0-1=1,1-1=0;
等式挪到右邊
0+0=0,1+0=1,1+1=0,0+1=1;
可以發現加法和減法的真值表完全相同,因此模2加和模2減結果相同。所以我們將被除數加上r和減去r,最終得到的余數應該相同。於是余數r可以直接接到原始信息之后,得到最終的CRC碼字。
反碼求和校驗:
反碼求和的過程更簡單一些,將原始信息每16bit取反,求和,結果存在檢驗和字段中,接收端同樣對每個16bit進行二進制反碼求和,接收方在計算中包含發送方存放的檢驗和,最終結果應該全為1.
為何全為1?我們簡化4位模擬該過程。假設發送端有1001,取反后0110,最終發送10010110,接收端收到后開始校驗,取反求和
0110 + 1001=1111
結果如預期所料。其實更重要的是,當遇到進位時的處理,反碼求和最高位遇到進位時,最高位進位后放到低位繼續求和。意味着對於四位的求和,超過1111則循環到1,這就是反碼補碼的時鍾循環原理,1111是4位反碼求和的最大數。一個數加上自己取反得到的數正是時鍾輪盤上最大那個數。接收端由於包含了發送端計算的反碼和。反碼和取反+反碼和 = 全1.
有了對這些原理的理解,相信自己也能實現CRC校驗和反碼求和校驗算法了。具體的代碼網上一大堆,這里就不貼了,僅看了代碼,只會復制,不會重寫。。。