美文网首页
【tcp】tcp 四次挥手是否可以去掉TIME-WAIT?

【tcp】tcp 四次挥手是否可以去掉TIME-WAIT?

作者: Bogon | 来源:发表于2023-06-23 01:27 被阅读0次

    关于这个TIME-WAIT,真是让人咬牙切齿!

    为了这个TIME-WAIT,搞出这么多补丁,一堆象牙塔里的专家为了解决一个理论上可能存在的问题又引出一大堆新问题,甚至搞出tcp_tw_recycle这样丧心病狂的东西。
    多少人因为这坑爹玩意导致的网站打不开,接口调不通,多少运维人员加班到深夜,甚至扣绩效罚款。
    这些学院派的专家到底有没有一点接地气的工程意识?

    80%的问题都由20%的tw引发,甚至在各种的TCP实现中,大量的代码在处理tw,我个人觉得这有点过了!
    引入tw状态是为了确认老数据到来或者消失,且等待时延那么久,这已经是很多年以前的事了,那时我可能刚出生,家里可能还没有装电话...那时的网络条件,引入这些机制是确实需要的,但是随着网络技术的发展,tw已经慢慢成了鸡肋。即便新的TCP连接被老的FIN终止又怎样,即使新的连接被老的劫持又能怎样,即便不考虑这些,MSL未免也太长了些吧,话说当年DDN年代,这个值就已经很久了...

    按我的想法来设计TCP挥手,去他的TIME-WAIT,就不该搞出这么个状态机。
    TCP挥手就不该搞四次,而且最后的last ack还是个孤儿报文(ACK无法确认)。
    所谓的优雅、体面对称都是扯淡。
    主动关闭方在收到被动关闭方发出的第三次挥手的fin报文时候直接就从FIN-WAIT2状态进入CLOSE状态,然后发一个RST给被动关闭方,over。
    被动关闭方收到这个RST也顺理成长章的进入close,如果这个RST丢失,也会触发被动关闭方重传第三次挥手的fin报文,由于主动关闭方此时已进入close状态仍然会触发RST,简直完美闭环。

    什么TIMEWAIT什么2MSL,什么快速回收之类奇技淫巧劳什子全部都不需要了,就是这么简单粗暴的新版四次挥手。不好么?

    简单画个草图,修正下四次挥手,如有不妥敬请指正。

    image.png

    题主是认真思考这个问题的,向一切技术权威挑战的勇气可嘉!

    TCP的RFC专家组是这样理解TCP Session的。一个session由五元组组成,假设为:

    • 1.1.1.1 (Server IP)
    • 2.2.2.2 (Client IP)
    • 443 (Server Port)
    • 5566 (Client Port)
    • tcp (Protcol)

    将这五元组运算其MD hash,即可得到其 Session ID =3cd0c4ab7b2c3fe981fedb28085bae22

    image.png

    假设TCP的断开连接的四次挥手,中间没有出现任何状况,成功完成。

    • Client发出的字节流,从第一个字节到最后一个字节,已经全部被Server接收。
    • Server发出的字节流,从第一个字节到最后一个字节,已经全部被Client接收。

    数据(字节流)交换完毕,这不就是通信的本质吗?
    为何主动关闭的一方(即最后发出ACK的一方),通常为Client,还要等待漫长的Time Window?

    因为各种莫名的原因(比如超时重传等等),网络的管道里依然滞留一些Duplicated Packet,虽然其中的一份到达了目的地,但是其它的Duplicated copy在关闭连接时,依然没有到达目的地。

    如果能有一种老化(aging)机制,让这个Session ID = 3cd0c4ab7b2c3fe981fedb28085bae22 陪着网络管道里的Duplicated copy一起慢慢老去,正如歌手赵咏华唱的《最浪漫的事》,直到消亡,是不是一个good idea?

    在管道里的Duplicated copy消亡之前,这个Session ID = 3cd0c4ab7b2c3fe981fedb28085bae22 不会被再次使用(重复使用)。

    这个Session ID由谁来记忆(维护)?
    通常由主动关闭的一方,即client来记忆这个Session ID。
    而被动关闭的一方,通常为Server,无需记忆Session ID,直接释放内存。

    Client可怜巴巴望着RFC专家,这个Session ID要记忆多久才能释放?
    RFC专家说,Duplicated copy什么时候消失,你什么时候忘记这个Session ID。

    通常Duplicated copy的生命极限= IP Packet TTL,而Maximum TTL = 255秒,所以你差不多等个4分钟,即240秒就可以释放这个Session ID。

    为什么是 255 秒?
    
    在IP协议中,TTL(Time To Live)是一个8位的字段,表示IP数据包在网络中可以经过的最大路由器跳数。
    每当一个IP数据包经过一个路由器时,TTL的值会被减少1,当TTL的值为0时,数据包就会被丢弃。
    这个机制可以防止数据包在网络中无限循环。
    
    TTL的最大值是255,这是因为TTL是用一个8位的字节来表示的。
    在二进制中,8位最大可以表示的数值是11111111,也就是255。因此,TTL的最大值被限制为255。
    
    在计算TTL的生命周期时,通常将TTL的值乘以时间单位(如秒),得到一个时间值。
    这个时间值通常被认为是数据包的生命周期,表示数据包在网络中可以存在的最长时间。
    因此,Duplicated copy的生命极限通常等于IP Packet TTL乘以时间单位。
    如果TTL的值为255,那么它的最大生命期就是255秒,也就是4分15秒。
    

    Client在耐心等待240秒之后,TimeWait定时器响,将Session ID = 3cd0c4ab7b2c3fe981fedb28085bae22 释放。
    之后,Client依然可以用2.2.2.2,端口号= 5566 来建立TCP连接,连接的Session ID =3cd0c4ab7b2c3fe981fedb28085bae22 。

    由于此时网络管道里的Duplicated copy,已经完全消失(至少理论上),不会与新的Session ID = 3cd0c4ab7b2c3fe981fedb28085bae22 有任何字节流的混淆,所以是可靠的、稳健的。

    当然TimeWait =240 秒是极其保守的,这个保守的数值诚如问题所描述,是由于当初网速如蜗牛所限(一秒几个KB),按照当前网速,个人感觉等待3-4秒概率上是可行的。

    还有另一个方法,TCP报文有一个timestamp option,可以根据一个tcp报文的时间戳和TCP syn/fin报文的时间戳进行比较:FIN时间戳>TCP报文的时间戳> SYN时间戳 的才是合法报文,这样压根无需等待TIME-WAIT即可直接close。
    但是由于每个client、server在时钟上可能不同步,所以timestamp可能不准确,所以这个方法仅是一个建议,仅供参考。

    这里提到的时间是指系统时钟的时间。每个计算机系统都有一个系统时钟,用来记录当前的时间。系统时钟可以通过硬件设备(如晶体振荡器)或者软件来实现。

    在TCP报文中,可以使用时间戳选项来记录报文的发送或接收时间。这个时间戳可以基于系统时钟的时间来获取。当报文经过网络传输时,时间戳可以用来判断报文的顺序和合法性,以及计算报文的往返时间等。

    然而,由于不同计算机系统的时钟可能存在微小的差异,也可能因为时钟漂移或时钟同步等原因导致时间戳的准确性受到影响。因此,在使用时间戳进行报文验证时,需要注意时钟同步的问题,以确保时间戳的准确性和可靠性。

    TimeWait 是为了确保与Session ID相关的Duplicated packet从网络里消失,在此期间不要重用这个Session ID,换句话说就是,不要重复使用这个五元组。

    相关文章

      网友评论

          本文标题:【tcp】tcp 四次挥手是否可以去掉TIME-WAIT?

          本文链接:https://www.haomeiwen.com/subject/nlicydtx.html