基本概念

CRC(Cyclic Redundancy Check,迴圈冗餘校驗),其實是個很古老的資料校驗方法了,記得以前大學<<微機原理>>和<<微機原理與介面技術>>課程都對其進行了介紹,其校驗準確度較之普通的奇偶校驗、校驗和等方法更高,當然計算也略微複雜;較之MD5、SHA1等演算法,CRC安全性和準確度方面又略顯不足,但計算較之這兩者明顯簡單,效率更高。所以如果僅僅針對網路資料的一致性校驗,即收發端資料的是否一致(因為在Socket程式設計裡,單次收到資料的長度和傳送資料的長度即使在阻塞模式下,也不一定是相同的,這個依賴於網路環境,雖然TCP協議保證了資料的完整性和一致性,但像這種人為對資料進行了分片的情況,在收到資料時視情況還是有必要進行一下校驗),針對這種校驗要求,CRC32是明顯足夠,也不會帶來很大的計算負擔。

CRC32的C語言實現

關於CRC32(即校驗碼是32位)實現理論原理,這裡不多說,網上有大把的資料,這裡主要探究一下怎樣用C語言高效的實現CRC32校驗演算法。
下面的演算法用到了查詢表的方法,這也是比較常見的以空間換時間的思想。
對於以按位元組校驗的CRC演算法實現中,一個位元組8bit,取值範圍0~255,每個位元組均是如此。因此可以生成一個0~255所有數的校驗結果的陣列,以後就是取這個陣列的值就可以了。
查詢表實現程式碼:

int init_crc32_table(uint32_t crc32_table[])
{
    uint32_t c;
    int i = 0;
    int bit = 0;

    for (i = 0; i < 256; i++) {
        c = (uint32_t)i;

        for (bit = 0; bit < 8; bit++) {
            if (c & 1) {
                c = (c >> 1) ^ (0xEDB88320)//此十六進位制數代表CRC32標準多項式;
            }
            else {
                c = c >> 1;
            }
        }
        crc32_table[i] = c;
    }
    return 0;
}

資料校驗程式碼:
uint32_t crc傳入的初始值為0xffffffff;

uint32_t make_crc(uint32_t crc, unsigned char *string, uint32_t size, uint32_t crc32_table[])
{

    while (size--)
        crc = (crc >> 8) ^ (crc32_table[(crc ^ *string++) & 0xff]);

    return crc;
}

後記

上面程式碼測試過,可以直接用,可以看出,CRC32的實現還是比較容易的,計算效率也不錯,如果不是對一致性檢測要求過高的話,可以考慮CRC32以及同系的CRC16、CRC8等演算法。

.