c - 字符数组的 RFC 1071 校验和
问题描述
我很难理解RFC 1071中的以下校验和算法:
The following "C" code algorithm computes the checksum with an inner
loop that sums 16-bits at a time in a 32-bit accumulator.
in 6
{
/* Compute Internet Checksum for "count" bytes
* beginning at location "addr".
*/
register long sum = 0;
while( count > 1 ) {
/* This is the inner loop */
sum += * (unsigned short) addr++;
count -= 2;
}
/* Add left-over byte, if any */
if( count > 0 )
sum += * (unsigned char *) addr;
/* Fold 32-bit sum to 16 bits */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);
checksum = ~sum;
}
我的目标是获取一个 char 数组并计算其校验和,但我不确定未定义的变量是什么。addr
和/或的数据类型是什么checksum
,如何将 char 数组转换为可用于校验和过程的格式?我知道 count 是存储在 addr 中的字节数。
编辑:到目前为止,我正在考虑将 char 数组转换为整数,然后获取字节数:
int char_int = sscanf(char_array, "%d", &i);
int addr = char_int;
int count = sizeof(char_int);
解决方案
由于内部循环以 16 位增量处理数据,addr
因此必须是指向 16 位值的指针,即uint16_t * addr
.
checksum
是您希望存储最终结果的任何数据类型。如果您正在计算 16 位校验和,它也将是uint16_t
.
注意sum
应该是unsigned long
,不是long
。它在实践中有效,因为网络数据包通常不够大,以至于校验和会溢出 a long
(数据包必须至少为 32K 字节)。但是,如果您正在编写通用代码,则应该进行防御性编码。
您可以在以下位置找到使用适当的可移植数据类型的实现:
http://www.microhowto.info/howto/calculate_an_internet_protocol_checksum_in_c.html
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);
}
推荐阅读
- python - Python:如何在对数空间中的两条曲线之间绘制等距曲线?
- ruby-on-rails - Docker Compose 和 Rails: Bundler::GemNotFound 在启动时。bundler 是不是在寻找正确的宝石?
- ios - 使用哪些访问级别使枚举仅可用于该项目
- android - 将值传递到另一个页面以打开 PDF
- java - The method addFilter(SerializablePredicate) in the type InMemoryDataProvider is not applicable for the arguments (( desc) -> {})
- python - 如何从 tkinter 的子窗口修改根窗口?
- angular - Angular 8 路由 + 导航:锁定组件
- google-analytics - 如何暗示 Google Analytics API 并在 asp.net mvc core 3.1 中显示它们
- maximo - Maximo Spatial:设置记录位置功能背后的机制是什么?
- excel - 根据另一个工作表中的可见范围删除行