计算udp校验和(反码求和)

C语言1:

#include <stdio.h>
#include <arpa/inet.h>

unsigned long checksum(char *buf,int nword)
{
    unsigned long sum;
    unsigned short *data = (unsigned short *) buf;

    for(sum=0; nword>0; nword--)
    {
        sum += *data;
        data++;
        sum = (sum>>16) + (sum&0xffff);
    }
    sum = ~checksum & 0xFFFF;
    return htons(sum); //转为大端字节序
}

void main(int argc, char *argv[])
{
    char b []  = "\0d\0e";
    unsigned long ret = checksum(b, 2);
    printf("checksum is: 0x%lx\n", ret);
    printf("checksum is: %lu\n", ret);

}

C语言2(github copilot):

#include <stdio.h>
#include <stdint.h>

uint16_t udp_checksum(uint8_t *data, size_t len) {
    uint32_t checksum = 0;

    // 如果数据长度是奇数,填充一个字节
    if (len % 2 != 0) {
        data[len] = 0;
        len++;
    }

    // 将字节数组分成16位的块并相加
    for (size_t i = 0; i < len; i += 2) {
        uint16_t word = (data[i] << 8) + data[i + 1];
        checksum += word;
        // 处理进位
        checksum = (checksum & 0xFFFF) + (checksum >> 16);
    }

    // 取反码
    checksum = ~checksum & 0xFFFF;
    return (uint16_t)checksum;
}

int main() {
    uint8_t data[] = {'a', 'b', 'c', 'd'};
    size_t len = sizeof(data) / sizeof(data[0]);
    printf("Checksum: 0x%04X\n", udp_checksum(data, len));
    return 0;
}

Python(Github copilot):

def udp_checksum(data):
    """下面是一个用Python编写的UDP校验和算法:
    ### 步骤:
    1. 定义一个函数 `udp_checksum`,接受一个字节数组作为参数。
    2. 将字节数组分成16位的块。
    3. 将所有16位块相加。
    4. 如果有进位,则将进位加到结果中。
    5. 取结果的反码。
    6. 返回低16位,就是校验和。
    """
    if len(data) % 2 != 0:
        data += b'\x00'  # 如果数据长度是奇数,填充一个字节

    checksum = 0
    for i in range(0, len(data), 2):
        # 这个公式是大端的算法,如果是小端可以写作(data[i+1] << 8) + data[i]
        word = (data[i] << 8) + data[i + 1]
        print(word)
        checksum += word
        checksum = (checksum & 0xFFFF) + (checksum >> 16)  # 处理进位

    checksum = ~checksum & 0xFFFF  # 取反码
    return checksum

# 示例用法
data = b'\0d\0e'
print(hex(udp_checksum(data)))  # 输出校验和

关于接收端验证的方法:

把整个需要校验的数据计算校验和(反码求和),如果结果为0x0000则结果就是正确的,或者计算原码求和(累加后不取反),结果为0xffff则就是正确的。网上有的说验证结果为0x0000,有的说验证结果为0xffff要了解其中的原因。

参考:
https://blog.csdn.net/weixin_28673511/article/details/130314065
https://zhuanlan.zhihu.com/p/74381973

发表回复