关于 TCP 校验和计算的问题

Posted

技术标签:

【中文标题】关于 TCP 校验和计算的问题【英文标题】:Questions regarding TCP checksum calculation 【发布时间】:2014-06-22 05:53:21 【问题描述】:

我有两个问题:

    RFC 793 声明校验和应通过 96 位伪标头、tcp 标头和数据计算。伪标头包括源 IP 地址和目标 IP 地址。这不是破坏了保持层分离的整个想法,因为现在当网络层开始使用不同大小的地址时,传输层也需要改变。

    在另一篇 SO 帖子中,我发现了以下 java 代码来计算校验和。

     private long computeChecksum( byte[] buf )
         int length = buf.length;
         int i = 0;
         long sum = 0;
         long data;
    
         // loop through all 16-bit words unless there's 0 or 1 byte left.
         while( length > 1 )
             data = ( ((buf[i] << 8) & 0xFF00) | ((buf[i + 1]) & 0xFF));
             sum += data;
             if( (sum & 0xFFFF0000) > 0 )
                 sum = sum & 0xFFFF;
                 sum += 1;
             
             i += 2;
             length -= 2;
         
    
         if (length > 0 ) // ie. there are 8 bits of data remaining.
             sum += (buf[i] << 8 & 0xFF00); // create a 16 bit word where the 8 lsb are 0's and add it to the sum.
             if( (sum & 0xFFFF0000) > 0) 
                 sum = sum & 0xFFFF;
                 sum += 1;
             
         
    
         sum = ~sum; 
         sum = sum & 0xFFFF;
         return sum;
     
    

有些东西我不明白为什么在该代码中需要它们。第一:

data = ( ((buf[i] << 8) & 0xFF00) | ((buf[i + 1]) & 0xFF));

二进制与的需要是什么?我不明白,因为 buf[i] 是一个字节,但被视为一个 int 并向左移动了 8 位。这不是已经保证结果看起来像:00000000 00000000 ???????? 00000000.

还有为什么 sum 和 data 声明为 long ?正如我所看到的,这两个变量都不会使用超过 17 位,那么为什么我们不能只使用 int 呢?最后他们甚至会这样做:sum = sum & 0xFFFF,它会丢弃除 16 个最低有效位之外的任何内容。

谢谢!

【问题讨论】:

【参考方案1】:

这不会破坏保持层分离的整个想法,因为现在当网络层开始使用不同大小的地址时,传输层也需要改变。

是的。事实上,这就是RFC 2460 重新定义 IPv6 的伪标头的原因:

任何传输或其他上层协议,包括 在其校验和计算中来自 IP 标头的地址必须是 修改为通过 IPv6 使用,包括 128 位 IPv6 地址 而不是 32 位 IPv4 地址。 [...]

【讨论】:

以上是关于关于 TCP 校验和计算的问题的主要内容,如果未能解决你的问题,请参考以下文章

TCP包里,关于IP头和TCP头的校验和字段

转移套接字的 TCP 校验和计算

TCP 校验和能否检测到错误?如果是,如何处理?

校验和计算方法

ip协议首部校验及tcp校验计算

什么是校验和?