TCP为何要连续发两次RST报文?

来自:车小胖谈网络 (微信号:chexiaopangnetwork),作者:车小胖谈网络

Wireshark抓的包,一次连接会出现两个RST的情况吗?

247,248出现了两个RST记录。是wireshark显示的不准确,还是实际就发送了两次。

 


 

这个问题很有讨论的价值,在过往的抓包经历中,也曾看到在TCP连接断开时,出现多次Reset报文。起初没有太在意,但是这种情况多次重复发生时,我意识到这不是一个偶然的现象,而是在TCP代码里实现的必然行为。

 

在讨论这个问题之前,让我们来回顾一下什么情况下,TCP什么时候会发生Reset报文?

 

在官方的RFC文档里,一般会这么描述:当TCP接收到对方的报文时,代码无法处理时,通常会发送Reset报文,将当前TCP连接尽快释放,以让对方重新建立一个TCP连接。

 

这些都是放之四海而皆准的官僚套话,一般来说以下情况会发送Reset报文:

 

  • TCP 目的端口没有侦听

  • 目的端口在侦听,但目的端口并没有绑定目的IP

  • 以上两种情况都没有问题,但是源IP无法接受

  • 以上三种情况都没有问题,但是源端口无法接受

  • 除了以上四种情况,报文无法继续处理,Reset是最佳选择等等N种情况

 

发送方发完Reset做点啥?当然是释放TCP连接所占用内存资源!

 

接收方接到Reset会做啥?当然也是释放TCP连接所占用内存资源!

 

这当然是理想中的情况,但是现实与理想之间总是有很大的鸿沟。现实的情况是,互联网、广域网、局域网丢包是家常便饭。如果TCPReset报文发出了,但是在到达接收方的路上丢了,会造成双方的TCP状态完全不同步,发送方完全释放,另一方依然健在。

 

如果健在的一方,稍后发送TCP报文,会触发完全释放的一方再次将Reset报文发出,健在的一方收到Reset消息,同样会将TCP连接占用的内存完全释放,这是一种非常普遍的场景。

 

但是,如果健在的一方迟迟没有报文发出,会一直勇敢地活下去。有同学会说,不就是占用一点内存资源吗?

 

这种无法释放的内存资源,对于服务器是一种累赘,越早释放越好。

 

连续两次发送Reset报文

可以一定程度上克服一个Reset报文丢失造成双方状态的不同步现象,毕竟两个报文都丢的概率要小于一个报文的丢失概率。

 

谈完这个话题,再来安利一下TCP的重要性。

 

不夸张的说,任何一个互联网工程师,如果没有理解TCP连接的状态同步,压根就没有理解什么是通信。在计算机网络的世界里,有很多状态同步的概念存在,路由协议OSPF的同步,路由协议BGP的状态同步,生成树的状态同步,组播树的状态同步,标签协议LDP的同步等等。


TCP做为互联网基础架构并且维护状态的一个协议,即基础又重要。所谓重要指的是,一旦深刻理解了TCP的状态同步,就打开了一扇通往互联网的大门。。。

推荐↓↓↓
程序员的那点事
上一篇:BGP路由泄露:互联网全球性灾难的元凶 下一篇:华为年薪201万的“顶尖人才”,看完他们的履历我哭了...