字符数组的RFC 1071校验和

字符数组的RFC 1071校验和,c,checksum,C,Checksum,我很难理解以下校验和算法: 我的目标是获取一个char数组并计算其校验和,但我不确定未定义的变量是什么。addr和checksum的数据类型是什么和/或如何将字符数组转换为可在校验和过程中使用的格式?我知道count是存储在addr中的任何内容的字节数 编辑:到目前为止,我正在考虑将字符数组转换为整数,然后获取字节数: int char_int = sscanf(char_array, "%d", &i); int addr = char_int; int count = sizeof(

我很难理解以下校验和算法:

我的目标是获取一个char数组并计算其校验和,但我不确定未定义的变量是什么。
addr
checksum
的数据类型是什么和/或如何将字符数组转换为可在校验和过程中使用的格式?我知道count是存储在addr中的任何内容的字节数

编辑:到目前为止,我正在考虑将字符数组转换为整数,然后获取字节数:

int char_int = sscanf(char_array, "%d", &i);
int addr = char_int;
int count = sizeof(char_int);

由于内部循环以16位增量处理数据,
addr
必须是指向16位值的指针,即
uint16\u t*addr

校验和
是您希望存储最终结果的任何数据类型。如果您正在计算16位校验和,它也将是
uint16\u t

请注意,
sum
可能应该是
无符号长的
,而不是
长的
。它在实践中起作用,因为网络数据包通常不够大,校验和将溢出
(数据包必须至少为32K字节)。但是,如果你在编写通用代码,你应该防御性地编写代码

您可以在以下位置找到使用适当的可移植数据类型的实现:

uint16\u t ip\u校验和(void*vdata,size\u t length){
//将数据指针强制转换为可以索引的指针。
字符*数据=(字符*)vdata;
//初始化蓄能器。
uint32_t acc=0xffff;
//处理完整的16位块。
用于(尺寸i=0;i+10xfff){
acc-=0xffff;
}
}
//处理数据末尾的任何部分块。
如果(长度&1){
uint16_t word=0;
memcpy(&word,data+length-1,1);
acc+=ntohs(字);
如果(acc>0xffff){
acc-=0xffff;
}
}
//以网络字节顺序返回校验和。
返回HTON(~acc);
}

我可以告诉您,您肯定不想使用
sscanf(字符数组、%d、&I)
;将写入的数字(如
“1234”
)转换为二进制,而此示例代码旨在将N个原始字节的序列视为(N/2)16位二进制数的序列。我还可以告诉您,所显示的代码非常古老,在现代C语言中所做的事情被认为是不正确的,因此您可能不应该将其用作参考。不幸的是,我没有更好的参考。我也在网上注意到了这个解决方案,但没有使用它,因为在我的例子中,我试图计算
int
,而不是
无符号int
校验和,并且无法导入
uint16\u 6
的库。如果我早就指定了,我深表歉意。@Paradox它是
uint16\u t
,如果您没有
stdint.h
,它可以在
中找到@Paradox,然后将
uint16\u t
的所有用法替换为
无符号短码
,还包括
限制.h
,并放入
\if-USHRT\MAX!=65535
#error“下面的代码假定无符号短码为16位”
#endif
就在include之后。
int char_int = sscanf(char_array, "%d", &i);
int addr = char_int;
int count = sizeof(char_int);
uint16_t ip_checksum(void* vdata,size_t length) {
    // Cast the data pointer to one that can be indexed.
    char* data=(char*)vdata;

    // Initialise the accumulator.
    uint32_t acc=0xffff;

    // Handle complete 16-bit blocks.
    for (size_t i=0;i+1<length;i+=2) {
        uint16_t word;
        memcpy(&word,data+i,2);
        acc+=ntohs(word);
        if (acc>0xffff) {
            acc-=0xffff;
        }
    }

    // Handle any partial block at the end of the data.
    if (length&1) {
        uint16_t word=0;
        memcpy(&word,data+length-1,1);
        acc+=ntohs(word);
        if (acc>0xffff) {
            acc-=0xffff;
        }
    }

    // Return the checksum in network byte order.
    return htons(~acc);
}