tcp序列号回绕与解决

问题描述

tcp协议头中有seq和ack_seq两个字段,分别代表序列号和确认号。tcp协议通过序列号标识发送的报文段。seq的类型是__u32,当超过__u32的最大值时,会回绕到0。

 

一个tcp流的初始序列号(ISN)并不是从0开始的,而是采用一定的随机算法产生的,因此ISN可能很大(比如(2^32-10)),因此同一个tcp流的seq号可能会回绕到0。而我们tcp对于丢包和乱序等问题的判断都是依赖于序列号大小比较的。此时就出现了所谓的tcp序列号回绕(sequence wraparound)问题。

 

内核解决办法

内核中给出的序列号(解决序列号回绕问题)判断解决方案十分简洁:

 

点击(此处)折叠或打开

  1. /*
  2. * The next routines deal with comparing 32 bit unsigned ints
  3. * and worry about wraparound (automatic with unsigned arithmetic).
  4. */
  5.  
  6. static inline int before(__u32 seq1, __u32 seq2)
  7. {
  8. return (__s32)(seq1-seq2) < 0;
  9. }
  10. #define after(seq2, seq1) before(seq1, seq2)

 

原理

为什么(__s32)(seq1-seq2)<0就可以判断seq1<seq2呢?这里的__s32是有符号整型的意思,而__u32则是无符号整型。< style="-ms-word-wrap: break-word;" div="">

 

为了方便说明,我们以unsigned char和char为例来说明:

假设seq1=255, seq2=1(发生了回绕)。

seq1 = 1111 1111 seq2 = 0000 0001

我们希望比较结果是seq1<seq2< style="-ms-word-wrap: break-word;" div="">

 

 seq1 - seq2=

 1111 1111

-0000 0001

-----------

 1111 1110

 

由于我们将结果转化成了有符号数,由于最高位是1,因此结果是一个负数,负数的绝对值为

 0000 0001 + 1 = 0000 0010 = 2

 

因此seq1 - seq2 < 0

 

注意:

如果seq2=128的话,我们会发现:

 seq1 - seq2=

 1111 1111

-1000 0000

-----------

 0111 1111

 

此时结果尤为正了,判断的结果是seq1>seq2。因此,上述算法正确的前提是,回绕后的增量小于2^(n-1)-1。

 

由于tcp序列号用的32位无符号数,因此可以支持的回绕幅度是2^31-1,满足要求了。

转自:https://blog.csdn.net/hi_software/article/details/51768026

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值