概述
- CRC(循环冗余校验码)是一种被广泛应用的错误验证机制,它使用特定的规则处理数据,计算出一个校验和,并与数据一起发送给接收方。接收方使用同样的规则计算CRC,如果两个计算结果一致则说明传输正确,否则表示传输过程发生了错误
- boost.crc库实现了计算CRC的功能,使用很方便。它位于名字空间boost,需要包含头文件
<boost/crc.hpp>
#include <boost/crc.hpp>
using namespace boost;
- crc库提供了两个类用于计算循环冗余校验码:一个是crc_basic,以bit为单位进行计算,速度慢,仅用于理论研究;另一个是crc_optimal,是优化过的处理机,以byte为单位进行计算,速度很快,适合于实际应用。crc库的所有实现均基于crc_optimal。
类摘要
template < std::size_t Bits ... >
class crc_optimal
{
public:
explicit crc_optimal( value_type init_rem = InitRem );
void reset( value_type new_rem = InitRem ); // 重置计算
void process_byte( unsigned char byte ); // 计算CRC值
void process_block( void const *bytes_begin, void const *bytes_end );
void process_bytes( void const *buffer, std::size_t byte_count );
value_type checksum() const; // 获得CRC值
void operator ()( unsigned char byte ); //调用操作符重载
value_type operator ()() const;
};
crc_optimal有6个模板参数,但我们通常无需关心这些细节,因为这涉及到CRC计算的很多数学理论知识。只有第一个模板参数Bits是比较重要的,它定义了CRC模板类的位数,一般是16或32
预定义的实现类
crc_optimal
类的模板参数过多,实际使用时很不方便,所以crc库基于crc_optimal预定义了四个实现类crc_16_type、crc_ccitt_type、crc_xmodem_type、crc_32_type。千3位是16为的CRC吗,第4个是32位的CRC码
typedef crc_optimal<16, 0x8005, 0, 0, true, true> crc_16_type;
typedef crc_optimal<16, 0x1021, 0xFFFF, 0, false, false> crc_ccitt_type;
typedef crc_optimal<16, 0x8408, 0, 0, true, true> crc_xmodem_type;
typedef crc_optimal<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true>
crc_32_type;
用法
- 为优化速度,crc_optimal只能以byte为单位处理数据(crc_basic可以处理bit)
- 成员函数process_byte()一次只能处理一个字节。process_bytes()和process_block()函数则可以处理任意长度的数据块,两者的区别在于输入参数:
process_bytes()
用"数据块+数据库长度"的形式,process_block()接受数据块的开始和结束指针 - 在任何时候crc_optimal都可以调用checksum()函数获得当前已计算出的CRC值,或者调用reset()重置计算结果
使用crc_32_byte计算crc的代码如下:
crc_32_type crc32;
cout << hex ;
cout << crc32.checksum() << "\n";
crc32.process_byte('a'); // 计算1个字节
cout << crc32.checksum() << "\n";
crc32.process_bytes("1234567890", 10); // 计算10个字节
cout << crc32.checksum() << "\n";
char szCh[] = "1234567890";
crc32.reset();
crc32.process_block(szCh, szCh + 10);
cout << crc32.checksum() << "\n";
- crc_optimal还重载了operator(),它有两种用法:不带参数的形式直接返回CRC值,相当于调用checksum(),可以很方便的获取返回值;带参数的形式接受一个字节,相当于调用process_byte(),因此可以把crc_optimal对象当作函数对象传递给标准算法:
crc_32_type crc32;
cout << hex;
crc32.process_bytes("1234567890", 10);
cout << crc32() << endl;
string str = "1234567890";
crc32.reset();
cout << crc32() << endl;
cout << std::for_each(str.begin(), str.end(), crc32)() << endl;
cout << crc32() << endl;
std::for_each算法接受一个单参的函数对象,把它拷贝一个副本在算法内部使用,不会影响原函数对象(即crc32)。算法在数据块区间逐个元素调用函数对象的operator(),即process_byte()计算CRC值,循环完成后返回存储的函数对象副本—另一个crc_32_type对象。