了解TCP校验功能 [英] Understanding the TCP checksum function
问题描述
我相信,TCP校验功能执行以下操作:
I believe that the TCP checksum function does the following:
- 分手的伪首和TCP分段报头和数据为2字节的块。
- 添加0的一个字节填充到最后一个块结束时,如果它不是2个字节,使其2个字节。
- 取之和的1的补数来获得TCP校验。
听起来很简单。因此,我写我自己的泛型校验
功能:
Sounds simple enough. Hence I wrote my own generic checksum
function:
#include <inttypes.h>
#include <arpa/inet.h>
uint16_t checksum(uint16_t * data, int size) {
uint16_t sum = 0;
int i = 0, length = size / 2;
while (i < length) sum += data[i++];
if (size % 2) sum += data[i] & 0xFF00;
return htons(~sum);
}
然而,其他人都写校验
功能,这似乎是更为复杂。例如:
However other people have written checksum
functions which seem to be more complicated. For example:
uint16_t checksum(uint16_t * addr, int len) {
int nleft = len;
int sum = 0;
uint16_t * w = addr;
uint16_t answer = 0;
while (nleft > 1) {
sum += *w++;
nleft -= sizeof(uint16_t);
}
if (nleft == 1) {
*(uint8_t *) (&answer) = *(uint8_t *) w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}
我有一个关于这个code几个问题:
I have a few questions regarding this code:
- 什么语句
*(uint8_t有*)(安培;回答)= *(uint8_t有*)瓦;?
实际上做 -
为什么我们采取的总和为:
- What does the statement
*(uint8_t *) (&answer) = *(uint8_t *) w;
actually do? Why do we take the sum as:
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
有没有计算TCP校验和变更的方式吗?
Did the way to calculate the TCP checksum change?
我真的不明白为什么我们做和=(总和&GT;&GT; 16)+(总和与放大器; 0xFFFF的)
。考虑之
是为0xABCD
:
I really don't see why we do sum = (sum >> 16) + (sum & 0xFFFF)
. Consider sum
is 0xABCD
:
0xABCD >> 16 == 0x0000
0xABCD & 0xFFFF == 0xABCD
0x0000 + 0xABCD == 0xABCD
这似乎是一个多余的步骤。这同样适用于下一条语句之和+ =(总和&GT;&GT; 16)。
推荐答案
出现校验功能是只大端处理器。
The checksum function appears to be for big-endian processors only.
第一个while循环进行了速度优化。
The first while loop is optimized for speed.
在&放大器;答案
招加载的最后一个字节(如果有字节数为奇数)到答案的高字节
,留下低字节为零,类似于您code确实与数据[1] - 放什么;为0xFF00
。它的工作方式是这样的
The &answer
trick loads the last byte (if there were an odd number of bytes) into the high byte of answer
, leaving the low byte zero, similar to what your code does with data[i] & 0xff00
. The way it works is this
1) take the address of answer (&answer)
2) convert that to a byte pointer (uint8_t *)
2a) on a big endian processor the first byte of a 16-bit quantity is the high byte
3) overwrite the high byte with the last byte of the data
校验应该与携带添加回计算。它这里假设这个code是一台机器,一个 INT
是上运行32位位。因此,(总和&安培; 0xFFFF的)
是16位校验和(总和&GT;&GT; 16)
是进位位(如果有的话)需要被加回在。因此,行
The checksum is supposed to be computed with the carries added back in. It's assumed here that this code is running on a machine where an int
is 32-bits. Therefore, (sum & 0xffff)
is the 16-bit checksum, and (sum >> 16)
are the carry bits (if any) that need to be added back in. Hence, the line
sum = (sum >> 16) + (sum & 0xffff);
调整总和包括携带。不过,该行的code本身可能产生的另一个进位。因此,下一行之和+ =(总和&GT;&GT; 16)。
补充说,进位(如果有的话)回校验
adjusts the sum to include the carries. However, that line of code could itself generate another carry bit. So the next line sum += (sum >> 16)
adds that carry (if any) back into the checksum.
最后,把那些补的答案。需要注意的是 htons
未使用,因为整个函数隐含假定它是一个大端处理器上运行。
Finally, take the ones-complement of the answer. Note that htons
is not used since the whole function implicitly assumes that it is running on a big endian processor.
这篇关于了解TCP校验功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!