2014-05-05 116 views
1

我有两个问题:关于TCP校验和计算问题

  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; 
    } 
    

有一些事情我不明白为什么他们需要的代码。第一个在:

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

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

此外,为什么sum和data声明为long?就我所见,两个变量都不会超过17位,所以为什么不能使用int?最后他们甚至可以这样做:sum = sum & 0xFFFF它丢弃除16个最低有效位以外的任何数据。

谢谢!

回答

2

这样做是否会破坏保持图层分离的整体思路,因为现在当网络层开始使用不同大小的地址时,传输层也需要更改。

是的。确实,这就是为什么RFC 2460重新定义了IPv6的伪首部:

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