有关TCP校验和计算的问题

时间:2014-05-05 20:01:13

标签: java tcp checksum

我有两个问题:

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

  2. 在另一篇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;
    }
    
  3. 有些事情我不明白为什么在该代码中需要它们。先进入:

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

    二进制AND的需求是什么?我不明白,因为buf [i]是一个字节,但被视为一个int并向左移8位。是不是已经保证结果如下:00000000 00000000 ???????? 00000000

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

    谢谢!

1 个答案:

答案 0 :(得分:2)

  

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

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

  

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