2016年6月29日星期三

TCP古董TIME_WAIT:为什么被动关闭的一方不需要TIME_WAIT傻等呢,似乎人人都了然了


突然想起了这个问题,原因自然可以猜测得到。可是奇怪的是,实在没找到有人问同样的问题,更没有看到什么地方说明原因。真...孤独。总觉得世界上一定有人想起过这个问题,只不过没人愿意提罢了,于是做个备忘录。

TIME_WAIT,是网络高手们的必经之路,有很多文章可参考,随便给一个我觉得写得很有经验的文章:你所不知道的TIME_WAIT和CLOSE_WAIT - 老男孩教育博客
用自己的话说,大致就是,
主动关闭连接的那一方呢,虽然也收到了对方的分手信号,可以说是顺利的完成了分手手续了,可是,它但还是担心对方有什么迟延数据等会儿会乱来,所以等几十几百秒。
  • 有道理啊,但是很傻,特别是对于Web Server这样的被动服务来说是很傻。

反正现状是,几乎所有的Web Server在创建时socket server时都指定了SO_REUSEADDR标记了,部分原因就是为了克服这个破TIME_WAIT时不让侦听的毛病。否则铁定被人投诉。同理,NodeJS之类的工具里也是这样处理了。
如果没有这个标记,那经常在Debug时手动停止或者不小心死了(反正都会引发这个TIME_WAIT)后,再次启动Web Server时,就会爆“地址有人在用了”,那谁能忍受啊。
Web Server:想开点,对自己好点,别扣着破标准了,我主动关闭了连接后,既然也收到了对方的结束信号了,那后面来的什么迟延数据关我啥事儿啊,发现乱数据我就回个RST,就算是出事儿也是对方那边出事儿。
所以呢,这么多年过来,也没人说Web Server和NodeJS这么有什么问题,那么多高手都盯着呢。
当然,这些大白话都不是什么严谨的话,扣字眼就没完没了了。
  • 而对于客户端,路由器,这些东西上面的TIME_WAIT还是不能简单无视的,这在上面的链接文章里有例子。


  • 我好奇的是,为什么被动关闭连接的那一方,当顺利的完成了分手手续后,不进入那该死的几十几百秒等待状态呢?

为什么文档上不明确添加个说明呢,光给出个状态图硬说:就是这样的状态迁移,你爱接受不接受。
随便给个链接:CLOSE_WAIT
输入图片说明
猜测一下,那是因为TCP是排序处理数据的,既然都收到了主动方发出的FIN信号(就是主动方发了一堆数据后单独发了个FIN表明完了),那就说明主动方的所有数据都已经接收到了,不存在什么迟到的数据的事儿了。之后一旦收到了主动方的ACK,那就OK了,干干净净分手。
猜测是猜测,可这东西又不好做实验,不找个100%肯定的文章我是不放心的,这是强迫症。
例如,如果主动方发来的FIN比之前的数据还早来,那分手之后,岂不是还是有可能对方的数据迟迟而来?不过幸好,TCP是检查顺序的,来早的FIN应该会被cache起来,并不立刻当真处理的。
这就是我要确认的内容,理论上显然是没错的,可实际上谁知道呢,我需要一个有经验的人的话才安心。
硬翻那协议说明的话,总是隔靴挠痒,不贴心,我就想要我的问题的答案。
还好,找到了有人明确这样说了,我就罢休了。 TCP数据流稳定性--TCP分片,重组及乱序 - 晓风残梦 - 博客园
TCP协议规定,对于收到的乱序报文并不丢弃,而是缓存下来(这样做是为了减少更多的重传),立即发送希望接受的报文确认。例如:发送端A发送了以下几个包:第一个:1001-1100,第二个1101-1200,第三个FIN包(序列号是1201,一个虚字节)。
1)第二个包在传输的过程中丢失了,接收端收到第三个包后并不丢弃,而是缓存下来,然后,立即发送一个ACK,确认号是1101(这样做的目的是不必等到发送端A的第二个包超时后重传,发送端A收到3个同样的ACK后立即重传,这是快速重传的概念)。


没有评论:

发表评论