目录
一:CRC校验简介
循环冗余校验,CRC校验,是一种根据网络数据包或者计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或者校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来做错误侦测的。
CRC校验计算速度快,检验能力强,易于用编码器等硬件电路实现。从检错的正确率与速度,成本等方面,都比奇偶校验等校验方式具有优势。因而,CRC成为计算机信息通信领域具为普遍的校验方式。常见的应用有以太网/USB通信,压缩解压,视频编码,图像存储,磁盘读写等。
二:CRC校验 实际应用案例 登录
CRC类
#ifndef CRC_H
#define CRC_H
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <string>
#include <cstdint>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
using namespace std;
class CRc
{
public:
CRc();
int crc32(char *parr,int parr_len);
};
#endif // CRC_H
#include "crc.h"
CRc::CRc()
{
}
int CRc::crc32(char *parr, int parr_len)
{
char* pbuf = NULL;
int PLOYNOMAL = 0xEDB88320;
// 数据长度为奇数,在数据前补0
if (1 == parr_len % 2)
{
parr_len += 1;
pbuf = new(std::nothrow) char[parr_len];
memset(pbuf, 0, parr_len);
memcpy(&pbuf[1], parr, parr_len - 1);
}
// 数据长度为偶数,原样复制数据
else
{
pbuf = new(std::nothrow) char[parr_len];
memcpy(pbuf, parr, parr_len);
}
// 申请空间失败
if (NULL == pbuf)
{
return 0;
}
// CRC为用来移位的32位数据结构,ploy为32位的生成多项式
unsigned long crc = 0, ploy = 0;
// CRC余数值
unsigned int crc_code = 0;
int i = 0, j = 0, k = 0;
// crc = 0xFFFF0000
// crc校验初始值为0
crc = 0;
ploy = 0x80000000;
// 求得32位的生成多项式
ploy = ploy ^ ((unsigned long)PLOYNOMAL << 15);
// for (i = 0; i < 2; i++) 实现编码前预置移位寄存器全为1
// 先讲数据项的前16位放入crc中
crc = ((unsigned long)pbuf[0] << 24) ^ ((unsigned long)pbuf[1] << 16);
// 该循环实现数据的移位,计算CRC余数
for (i = 2; i < (int)parr_len + 1; i += 2)
{
// 判断pbuf数据项是否移位完毕
if (i < (int)parr_len)
{
// 如果没有移位完毕,则移入pbuf[i]、pbuf[i+1]
crc = crc ^ ((unsigned long)pbuf[i] << 8) ^ ((unsigned long)pbuf[i + 1]);
}
// 移位完毕,则移入0000 到 CRC的低16位
else
{
// 由于必须从数据项的第一位为“1”的位开始移位,必须要舍去数据项第一位为“1”的位置前所有的0
crc = crc & 0xFFFF0000;
}
if (2 == i)
{
// 舍0
while (!(crc & 0x80000000))
{
crc = crc << 1;
// K为舍去的0的个数
k = k + 1;
if (0 == crc)
break;
}
// 由于舍去K个0, 因此只需进行16-K次移位
for (j = 0; j < (16 - k); j++)
{
// 判断移出的是否为1
if (crc & 0x80000000)
crc = ((crc ^ ploy) << 1);
else
crc = crc << 1;
}
}
else
{
for (j = 0; j < 16; j++)
{
// 判断移出的是否为1
if (crc & 0x80000000)
crc = ((crc ^ ploy) << 1);
else
crc = crc << 1;
}
}
}
crc_code = (unsigned int)(crc >> 16);
// 清除缓冲
delete[] pbuf;
pbuf = NULL;
// 返回计算结果
return crc_code;
}
登录 案例
#include"crc.h"
//登录验证函数
void Login::on_login_butt_clicked()
{
QString captcha = ui->code_edit->text();
//
if(captcha.toLower() == this->code.toLower())
{
HEAD head;
char buffer[sizeof(HEAD) + sizeof(User_Request)] = { 0 };
head.type=1001;
memcpy(head.account,this->ui->name_edit->text().toStdString().c_str(),sizeof (this->ui->name_edit->text()));
head.packet_len = sizeof (regist);
char buf[500]={0};
QByteArray str;
QByteArray bytePwd = this->ui->pwd_edit->text().toUtf8();//指定加密格式
str = QCryptographicHash::hash(bytePwd,QCryptographicHash::Md5);
QString pwdstr = str.toHex();
memcpy(regist.accout,this->ui->name_edit->text().toStdString().c_str(),sizeof (this->ui->name_edit->text()));
memcpy(regist.password,pwdstr.toStdString().c_str(),sizeof (pwdstr));
char str1[500] = {0};
memcpy(str1,®ist,sizeof (this->regist));
CRc *scrc = new CRc();
uint32_t CRC = scrc->crc32(str1,head.packet_len);
head.crc32 = CRC;
qDebug()<<CRC;
//拷贝包体+包体
memcpy(buffer, &head, sizeof(HEAD));
memcpy(buffer + sizeof(HEAD), ®ist, sizeof(User_Request));
write(SingleDB::getInstance()->get_fd(), buffer, sizeof(HEAD) + sizeof(User_Request));
return;
}
else
{
QMessageBox::warning(this, tr("警告!"),tr("验证码错误!"),QMessageBox::Yes);
this->code = this->getcode();
}
}