CRC通信校验

本文详细介绍了CRC(循环冗余校验)在TCP通信中的作用,展示了如何在Python、Qt和C++中实现CRC-16算法来验证数据包完整性,并提供了示例代码。
摘要由CSDN通过智能技术生成

CRC(循环冗余校验)是一种常用的错误检测技术,用于验证数据在传输过程中是否出现了错误。在TCP通信中,CRC通常被用来检验数据包的完整性。

CRC通过对数据进行多项式除法来生成一个校验码,发送方在发送数据时计算CRC并将其附加到数据包中,接收方收到数据后也计算CRC,并与接收到的CRC进行比较,如果两者一致,则说明数据在传输过程中没有出现错误。

在TCP通信中,CRC通常是通过硬件或者软件实现的,以保证数据的可靠传输。CRC的选择取决于通信的需求和环境,不同的应用可能会选择不同的CRC算法和参数。

1.python CRC校验例程

假设我们有一个简单的TCP通信场景,发送方希望将一个数据包发送给接收方,并使用CRC来验证数据包的完整性。这里我们可以使用一个简单的CRC算法,比如CRC-16。以下是一个简单的Python代码示例,演示了如何计算CRC并将其附加到数据包中,以及接收方如何验证CRC以确保数据完整性:

import crcmod.predefined
import struct

# 初始化CRC对象,使用CRC-16算法
crc16 = crcmod.predefined.Crc('crc-16')

def calculate_crc(data):
    # 计算CRC
    crc16.update(data)
    return crc16.crcValue

def append_crc(data):
    # 计算CRC并将其附加到数据后面
    crc = calculate_crc(data)
    crc_bytes = struct.pack('!H', crc)  # 使用big-endian编码
    return data + crc_bytes

def validate_crc(data_with_crc):
    # 提取数据和CRC
    data = data_with_crc[:-2]  # 最后两个字节是CRC
    received_crc = data_with_crc[-2:]

    # 计算接收到的数据的CRC
    expected_crc = calculate_crc(data)

    # 验证CRC
    return received_crc == struct.pack('!H', expected_crc)

# 示例数据包
data_packet = b'Hello, world!'
# 向数据包附加CRC
data_packet_with_crc = append_crc(data_packet)

# 模拟数据包传输过程
# 发送方发送数据包给接收方
# 接收方收到数据包后验证CRC
is_valid = validate_crc(data_packet_with_crc)
if is_valid:
    print("数据包完整,CRC验证通过")
else:
    print("数据包不完整,CRC验证失败")

这个例子中,我们使用了Python的crcmod库来计算CRC,并使用struct库来处理二进制数据的编码和解码。在这个例子中,CRC-16是通过crcmod库中的预定义CRC对象实现的,你也可以根据你的需求选择其他CRC算法和参数。

2.QT CRC校验例程

以下是一个使用Qt库的简单示例,演示了如何计算CRC并将其附加到数据包中,以及接收方如何验证CRC以确保数据完整性:

#include <QCoreApplication>
#include <QByteArray>
#include <QDebug>

// CRC-16算法
quint16 calculateCRC(const QByteArray &data) {
    quint16 crc = 0xFFFF;
    for (int i = 0; i < data.size(); ++i) {
        crc ^= (quint8)data.at(i);
        for (int j = 0; j < 8; ++j) {
            if (crc & 0x0001)
                crc = (crc >> 1) ^ 0xA001;
            else
                crc >>= 1;
        }
    }
    return crc;
}

// 向数据包附加CRC
QByteArray appendCRC(const QByteArray &data) {
    quint16 crc = calculateCRC(data);
    QByteArray result = data;
    result.append((crc & 0xFF00) >> 8);
    result.append(crc & 0x00FF);
    return result;
}

// 验证CRC
bool validateCRC(const QByteArray &dataWithCRC) {
    if (dataWithCRC.size() < 2)
        return false;

    quint16 receivedCRC = ((quint8)dataWithCRC.at(dataWithCRC.size() - 2) << 8) | ((quint8)dataWithCRC.at(dataWithCRC.size() - 1));
    QByteArray data = dataWithCRC.left(dataWithCRC.size() - 2);
    quint16 expectedCRC = calculateCRC(data);

    return receivedCRC == expectedCRC;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 示例数据包
    QByteArray dataPacket = "Hello, world!";

    // 向数据包附加CRC
    QByteArray dataPacketWithCRC = appendCRC(dataPacket);

    // 模拟数据包传输过程
    // 发送方发送数据包给接收方
    // 接收方收到数据包后验证CRC
    bool isValid = validateCRC(dataPacketWithCRC);
    if (isValid) {
        qDebug() << "数据包完整,CRC验证通过";
    } else {
        qDebug() << "数据包不完整,CRC验证失败";
    }

    return a.exec();
}

在这个例子中,我们使用了Qt库中的QByteArray来处理字节数组,以及QDebug来输出调试信息。计算CRC的函数是根据CRC-16标准算法编写的,它逐字节处理数据并计算出CRC值。然后,我们将计算出的CRC附加到数据包的末尾,发送给接收方。接收方收到数据后,提取出数据和CRC,然后计算接收到的数据的CRC值,并与接收到的CRC进行比较,以验证数据的完整性。

3.C++ CRC校验例程

下面是一个没有Qt依赖的纯C++版本的示例:

#include <iostream>
#include <string>
#include <vector>

// CRC-16算法
uint16_t calculateCRC(const std::string &data) {
    uint16_t crc = 0xFFFF;
    for (size_t i = 0; i < data.size(); ++i) {
        crc ^= static_cast<uint8_t>(data.at(i));
        for (int j = 0; j < 8; ++j) {
            if (crc & 0x0001)
                crc = (crc >> 1) ^ 0xA001;
            else
                crc >>= 1;
        }
    }
    return crc;
}

// 向数据包附加CRC
std::string appendCRC(const std::string &data) {
    uint16_t crc = calculateCRC(data);
    std::string result = data;
    result.push_back(static_cast<char>((crc & 0xFF00) >> 8));
    result.push_back(static_cast<char>(crc & 0x00FF));
    return result;
}

// 验证CRC
bool validateCRC(const std::string &dataWithCRC) {
    if (dataWithCRC.size() < 2)
        return false;

    uint16_t receivedCRC = (static_cast<uint8_t>(dataWithCRC.at(dataWithCRC.size() - 2)) << 8) |
                           static_cast<uint8_t>(dataWithCRC.at(dataWithCRC.size() - 1));
    std::string data = dataWithCRC.substr(0, dataWithCRC.size() - 2);
    uint16_t expectedCRC = calculateCRC(data);

    return receivedCRC == expectedCRC;
}

int main() {
    // 示例数据包
    std::string dataPacket = "Hello, world!";

    // 向数据包附加CRC
    std::string dataPacketWithCRC = appendCRC(dataPacket);

    // 模拟数据包传输过程
    // 发送方发送数据包给接收方
    // 接收方收到数据包后验证CRC
    bool isValid = validateCRC(dataPacketWithCRC);
    if (isValid) {
        std::cout << "数据包完整,CRC验证通过" << std::endl;
    } else {
        std::cout << "数据包不完整,CRC验证失败" << std::endl;
    }

    return 0;
}

这个版本中,我们使用了std::string代替QByteArray来处理字节数组,使用std::cout代替QDebug来输出调试信息。其他逻辑保持不变。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我写代码菜如坤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值