TCP/IP中TIME_WAIT状态详解

TIME_WAIT状态原理:

通信双方建立连接后,主动关闭连接的一方就会进入TIME_WAIT状态。

客户端主动关闭连接时,会发送最后一个ACK确认,然后就会进入TIME_WAIT状态,再停留2MSL,就会进入CLOSED状态。

接下来我们看一张图,来说明这一过程:

上图是TCP“四次挥手”的过程,相信你们都会很了解,下面我们来说说为什么要存在TIME_WAIT状态

TIME_WAIT状态存在的理由如下:

(1)可靠地实现TCP全双工连接的终止

TCP协议在关闭连接的四次挥手中,最终的ACK是由主动关闭连接的一端(A端)发出的,如果这个ACK丢失,对方(B端)将 重发出最终的FIN,因此A 端必须维护状态信息(TIME_WAIT)允许它重发最终的ACK.如果A端不维持TIME_WAIT状态,而是处于CLOSED状态,那么A端将响应RST报文段,B端收到后,将此报文段解释成一个错误。因而,要实现TCP全双工的正常终止,必须处理终止过程中四个分节任何一个报文段丢失的情况,主动关闭连接的A端必须维持TIME_WAIT状态。

(2)允许老的报文段在网络中消失

TCP报文段可能由于路由器异常而“迷路”,在迷途期间,TCP发送端可能因为确认超时而而重发这个分组,迷路的分组在路由器修复后也会被送到最终目的地,这个迟到的分组到达时就会引起问题,在关闭前一个连接之后,B又收到这个早已失效的连接请求报文段后,就误认为是A又发出一次新的连接请求,于是就向A发出确认报文段,同意建立连接。假定不采用三次握手,只要B发出确认,新的连接就建立了。为了避免这种情况,TCP协议不允许处于TIME_WAIT状态的A端再次建立一个新的连接,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个新TCP连接之后,来自旧连接的重复分组已在网络中消失了。

TIME_WAIT状态持续时间是2MSL(在我的下一篇博客中会讲解)时间,大概是1~4分钟,windows操作系统就是4分钟。

下面我们来进一步讨论这个问题:

客户端主动关闭连接

注意一个问题,进入TIME_WAIT状态的一般情况下是客户端。大多数服务器端一般执行被动关闭,服务器不会进入TIME_WAIT状态。当在服务器端关闭某个服务再重启时,服务器是会进入TIME_WAIT状态的。

举个例子:

1.客户端连接服务器端的80服务,这时客户端会启用一个本地的端口访问服务器的80,访问完成后关闭此连接,立刻再次访问服务器的80,这时客户端会启用本地的另一个端口,而不是刚才使用的那个本地端口,原因就是刚才的那个连接还处于TIME_WAIT状态。

2.客户端连接服务器的80服务,这时服务器关闭80端口,立刻再次重启80端口的服务,这时可能不会成功启动,原因也是服务器的连接还处于TIME_WAIT状态。

服务器提供服务时,一般监听一个端口就够了(例如80端口),客户端则是使用一个本地的空闲端口(大于1024),与服务器的80端口建立连接,当通信使用短连接,并且由客户端主动关闭连接时,主动关闭连接的客户端会产生TIME_WAIT状态的连接,一个TIME_WAIT状态的连接就占用了一个本地端口。这样在TIME_WAIT状态结束之前,本地最多能承受6万多个TIME_WAIT状态的连接,就无端口可用了。客户端与服务器进行短连接的TCP通信,如果在同一台机器上进行压力测试模拟上万的客户请求,并且循环与服务器端进行短连接通信,那么这台机器将产生4000个左右的TIME_WAITsocket,后续的短连接就会产生address already in use:connect的异常。

服务器端主动关闭连接

服务器提供服务时,一般监听一个端口就够了(例如80端口),客户端则是使用一个本地的空闲端口(大于1024),与服务器的80端口建立连接,当通信使用短连接,并且由服务端主动关闭连接时,主动关闭连接的服务端会产生TIME_WAIT状态的连接。由于都连接到服务器端80端口,服务器端的TIME_WAIT状态的连接会有很多个,假如server一秒钟处理1000个请求,那么就会积压240秒*1000=24万个TIME_WAIT的记录,服务器有能力维护这24万个记录。

大多数服务器端一般执行被动关闭,服务器不会进入TIME_WAIT状态,服务端为了解决这个TIME_WAIT问题,可选的方式有3种:

(1)保证由客户端主动发起关闭

(2)关闭的时候使用RST方式

(3)对处于TIME_WAIT状态的TPC允许重用

我们来总结一下:

通过上面的讨论,我们知道TIME_WAIT状态是友好的,并不是多余的,TCP要保证在所有可能的情况下使得所有的数据都能够正确送达。当你关闭一个scket时,主动关闭一端的socket将进入TIME_WAIT状态,而被动关闭的一方则进入CLOSED状态,这的确能够保证所有的数据都被传送。当一个SOCKET关闭的时候,是通过两端四次挥手完成的,当一端调用close()时,就说明本端没有数据要传送了,这好似看来在握手完成以后,socket就可以处于CLOSED状态了,其实不然,原因是这样安排状态有两个问题,首先我们没有任何机制保证最后的一个ACK能够正常传输,第二,网络仍然可能有残余的数据包,我们也必须能够正常处理。TIME_WAIT状态就是为了解决这两个问题而生的!!!!。

时间: 2024-12-11 10:47:23

TCP/IP中TIME_WAIT状态详解的相关文章

TCP/IP协议--TIME_WAIT状态存在的原因

1. 实际问题         初步查看发现,无法对外新建TCP连接时,线上服务器存在大量处于TIME_WAIT状态的TCP连接(最多的一次为单机10w+,其中引起报警的那个模块产生的TIME_WAIT约2w),导致其无法跟下游模块建立新TCP连接. TIME_WAIT涉及到TCP释放连接过程中的状态迁移,也涉及到具体的socket api对TCP状态的影响,下面开始逐步介绍这些概念. 2. TCP状态迁移        面向连接的TCP协议要求每次peer间通信前建立一条TCP连接,该连接可抽

TCP/IP详解--TCP连接中TIME_WAIT状态过多

转载自http://blog.csdn.net/yusiguyuan/article/details/21445883 TIMEWAIT状态本身和应用层的客户端或者服务器是没有关系的.仅仅是主动关闭的一方,在使用FIN|ACK|FIN|ACK四分组正常关闭TCP连接的时候会出现这个TIMEWAIT.服务器在处理客户端请求的时候,如果你的程序设计为服务器主动关闭,那么你才有可能需要关注这个TIMEWAIT状态过多的问题.如果你的服务器设计为被动关闭,那么你首先要关注的是CLOSE_WAIT. 原则

网络编程Socket之TCP之TIME_WAIT状态详解

下面我们用最简单的一对一的客户服务器模型来重现编程中遇到的一些问题: 初学socket的时候在编写socket程序的时候会遇到很多莫名其妙的问题,比如说bind函数返回的常见错误是EADDRINUSE 使用下面的程序重现这个状态: client: int main(int argc, const char * argv[]) { struct sockaddr_in serverAdd; bzero(&serverAdd, sizeof(serverAdd)); serverAdd.sin_fa

TCP/IP三次握手详解

原文:http://www.cnblogs.com/CBDoctor/archive/2012/10/17/2727073.html 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接. 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认: 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态: 第

OSI七层与TCP/IP五层网络架构详解

OSI和TCP/IP是很基础但又非常重要的网络基础知识,理解得透彻对运维工程师来说非常有帮助. (1)OSI七层模型 OSI中的层 功能 TCP/IP协议族 应用层 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 表示层 数据格式化,代码转换,数据加密 没有协议 会话层 解除或建立与别的接点的联系 没有协议 传输层 提供端对端的接口 TCP,UDP 网络层 为数据包选择路由 IP,ICMP,RIP,OSPF,BGP,IGMP 数据链路

netstat 中timewait状态详解

netstat下time_wait状态的tcp连接: 1.这是一种处于连接完全关闭状态前的状态: 2.通常要等上4分钟(windows server)的时间才能完全关闭: 3.这种状态下的tcp连接占用句柄与端口等资源,服务器也要为维护这些连接状态消耗资源: 4.解决这种time_wait的tcp连接只有让服务器能够快速回收和重用那些TIME_WAIT的资源:修改注册表[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Para

TCP/IP数据包格式详解-包括数据链路层的头部

图中括号中的数字代表的是当前域所占的空间大小,单位是bit位. 黄色的是数据链路层的头部,一共14字节 绿色的部分是IP头部,一般是20字节 紫色部分是TCP头部,一般是20字节 最内部的是数据包内容 黄色部分:链路层 目的MAC:当前step目的主机的mac地址 源MAC:当前step的源主机的mac地址 类型:指定网络层所用的协议类型,通常是IP协议,0x0800 绿色部分:网络层,这里用的是IP包头格式 版本:记录数据报属于哪一个版本的协议,如IPv4或IPv6 首部长度:指明IP头部长度

TCP/IP中最高大上的链路层详解(二)

引言 对于程序猿来讲,似乎越接近底层,就越显得高大上.这也算是程序猿们的共同认知吧,虽然不是所有人.今天LZ就和各位一起探讨一下TCP/IP中最高大上的一层,也就是最底层的链路层. 这一层LZ了解的还不够深刻,但是LZ还没有做硬件的打算,因此LZ觉得只要能够大致明白其原理即可,有的时候太执着了并不是好事,别忘了执着的同义词中有一个叫钻牛角尖. 链路层是什么 这个问题其实很好回答,在上一章LZ就提到过,直观的说,链路层就是我们平时接触的网卡和网卡的驱动程序(当然,也可以指其它的网络接口和驱动,比如

TCP协议状态详解

原文出自:Vimer的程序世界 1.建立连接协议(三次握手)(1)客户端发送一个带SYN标志的TCP报文到服务器.这是三次握手过程中的报文1.(2) 服务器端回应客户端的,这是三次握手中的第2个报文,这个报文同时带ACK标志和SYN标志.因此它表示对刚才客户端SYN报文的回应:同时又标志SYN给客户端,询问客户端是否准备好进行数据通讯.(3) 客户必须再次回应服务段一个ACK报文,这是报文段3. 2.连接终止协议(四次握手) 由于TCP连接是全双工的,因此每个方向都必须单独进行关闭.这原则是当一