精华内容
下载资源
问答
  • CLOSE_WAITTIME_WAIT
    千次阅读
    2022-03-25 14:52:51

    TIME_WAIT

    TIME_WAIT 是主动关闭链接时形成的,等待2MSL时间,约4分钟。主要是防止最后一个ACK丢失。 由于TIME_WAIT 的时间会非常长,因此server端应尽量减少主动关闭连接

    CLOSE_WAIT
    在被动关闭连接情况下,在已经接收到FIN,但是还没有发送自己的FIN的时刻,连接处于CLOSE_WAIT状态。

    CLOSE_WAIT是被动关闭连接是形成的。根据TCP状态机,服务器端收到客户端发送的FIN,则按照TCP实现发送ACK,因此进入CLOSE_WAIT状态。但如果服务器端不执行close(),就不能由CLOSE_WAIT迁移到LAST_ACK,则系统中会存在很多CLOSE_WAIT状态的连接。此时,可能是系统忙于处理读、写操作,而未将已收到FIN的连接,进行close。此时,recv/read已收到FIN的连接socket,会返回0。

    更多相关内容
  • 近期服务器出现大量time_wait的TCP连接造成服务器连接数过多而最终导致tomcat假死状态。连接服务器查看连接数的时候提示如下。 [root@test apache-tomcat-7.0.53]# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a...
  • 解决TIME_WAIT过多造成的问题
  • 主要介绍了apache time_wait连接数太多问题解决方法,本文使用调整内核参数来解决,需要的朋友可以参考下
  • 详细描述TCP的各个状态,初学者可以快速理解掌握tcp状态图
  • 本篇文章是对如何减少Linux服务器TIME_WAIT过多的问题进行了详细的分析介绍,需要的朋友参考下
  • 然后被动关闭的一方,进入CLOSE_WAIT状态,主动关闭的一方等待对方关闭,则进入FIN_WAIT_2状态;此时,主动关闭的一方 等待 被动关闭一方的应用程序,调用close操作。 被动关闭的一方在完成所有数据发送后,调用...

    1.Socket的关闭的过程(四次挥手)

    • 主动关闭连接的一方,调用close();协议层发送FIN包
    • 被动关闭的一方收到FIN包后,协议层回复ACK;然后被动关闭的一方,进入CLOSE_WAIT状态,主动关闭的一方等待对方关闭,则进入FIN_WAIT_2状态;此时,主动关闭的一方 等待 被动关闭一方的应用程序,调用close操作。
    • 被动关闭的一方在完成所有数据发送后,调用close()操作;此时,协议层发送FIN包给主动关闭的一方,等待对方的ACK,被动关闭的一方进入LAST_ACK状态;
    • 主动关闭的一方收到FIN包,协议层回复ACK;此时,主动关闭连接的一方,进入TIME_WAIT状态;而被动关闭的一方,进入CLOSED状态
    • 等待2MSL时间,如没发现重传的FIN,主动关闭的一方,结束TIME_WAIT,进入CLOSED状态

    说明:TCP协议规定,对于已经建立的连接,网络双方要进行四次握手才能成功断开连接,如果缺少了其中某个步骤,将会使连接处于假死状态,连接本身占用的资源不会被释放。

    • CLOSED:无连接是活动的或正在进行
    • LISTEN:服务器在等待进入呼叫
    • SYN_RECV:一个连接请求已经到达,等待确认
    • SYN_SENT:应用已经开始,打开一个连接
    • ESTABLISHED:正常数据传输状态
    • FIN_WAIT1:应用说它已经完成
    • FIN_WAIT2:另一边已同意释放
    • ITMED_WAIT:等待所有分组死掉
    • CLOSING:两边同时尝试关闭
    • TIME_WAIT:另一边已初始化一个释放
    • LAST_ACK:等待所有分组死掉

    2.time_wait 产生原因(存在的合理性)(等待2MSL意义)

    MSL:报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间。

    原因有二:

    • 保证TCP协议的全双工连接能够可靠关闭
    • 保证这次连接的重复数据段从网络中消失

    第一点:如果主机1直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致主机2没有收到主机1最后回复的ACK。那么主机2就会在超时之后继续发送FIN,此时由于主机1已经CLOSED了,就找不到与重发的FIN对应的连接。所以,主机1不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。

    第二点:如果主机1直接CLOSED,然后又再向主机2发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达主机2,由于新连接和老连接的端口号是一样的,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。

    3.time_wait过多产生原因

    在高并发短连接的TCP服务器上,当服务器处理完请求后立刻主动正常关闭连接。主动关闭的一方在发送最后一个 ack 后就会进入TIME_WAIT 状态 停留2MSL(max segment lifetime)的时间,这个场景下,会出现大量socket处于TIMEWAIT状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上。

    • 高并发让服务器在短时间范围内同时占用大量端口,而端口只0~65535的范围,有限
    • 短连接表示“业务处理+传输数据的时间 远远小于 TIMEWAIT超时的时间”的连接。

    说明:正常的TCP客户端连接在关闭后,会进入一个TIME_WAIT的状态,持续的时间一般在1-4分钟,对于连接数不高的场景,1-4分钟其实并不长,对系统也不会有什么影响,但如果短时间内(例如1s内)进行大量的短连接,则可能出现这样一种情况:客户端所在的操作系统的socket端口和文件描述符被用尽,系统无法再发起新的连接!

    举例来说:

    假设每秒建立了1000个短连接(Web场景下是很常见的,例如每个请求都去访问memcached),假设TIME_WAIT的时间是1分钟,则1分钟内需要建立6W个短连接,由于TIME_WAIT时间是1分钟,这些短连接1分钟内都处于TIME_WAIT状态,都不会释放,而Linux默认的本地端口范围配置是:net.ipv4.ip_local_port_range = 32768 61000不到3W,因此这种情况下新的请求由于没有本地端口就不能建立了。

    4.time_wait过多解决方法

    方法1:可以改为长连接,但代价较大,长连接太多会导致服务器性能问题并且安全性也较差;

    方法2:修改ipv4.ip_local_port_range,增大可用端口范围,但只能缓解问题,不能根本解决问题;

    方法3:客户端机器打开tcp_tw_reuse和tcp_timestamps选项;

    字面意思,reuse TIME_WAIT状态的连接。时刻记住一条socket连接,就是那个五元组,出现TIME_WAIT状态的连接,一定出现在主动关闭连接的一方。所以,当主动关闭连接的一方,再次向对方发起连接请求的时候(例如,客户端关闭连接,客户端再次连接服务端,此时可以复用了;负载均衡服务器,主动关闭后端的连接,当有新的HTTP请求,负载均衡服务器再次连接后端服务器,此时也可以复用),可以复用TIME_WAIT状态的连接。

    通过字面解释,以及例子说明,你看到了,tcp_tw_reuse应用的场景:某一方,需要不断的通过“短连接”连接其他服务器,总是自己先关闭连接(TIME_WAIT在自己这方),关闭后又不断的重新连接对方。

    那么,当连接被复用了之后,延迟或者重发的数据包到达,新的连接怎么判断,到达的数据是属于复用后的连接,还是复用前的连接呢?那就需要依赖前面提到的两个时间字段了。复用连接后,这条连接的时间被更新为当前的时间,当延迟的数据达到,延迟数据的时间是小于新连接的时间,所以,内核可以通过时间判断出,延迟的数据可以安全的丢弃掉了。

    这个配置,依赖于连接双方,同时对timestamps的支持。同时,这个配置,仅仅影响outbound连接,即做为客户端的角色,连接服务端[connect(dest_ip, dest_port)]时复用TIME_WAIT的socket。

    方法4:客户端机器打开tcp_tw_recycle和tcp_timestamps选项;

    字面意思,销毁掉 TIME_WAIT。

    当开启了这个配置后,内核会快速的回收处于TIME_WAIT状态的socket连接。多快?不再是2MSL,而是一个RTO(retransmission timeout,数据包重传的timeout时间)的时间,这个时间根据RTT动态计算出来,但是远小于2MSL。

    有了这个配置,还是需要保障 丢失重传或者延迟的数据包,不会被新的连接(注意,这里不再是复用了,而是之前处于TIME_WAIT状态的连接已经被destroy掉了,新的连接,刚好是和某一个被destroy掉的连接使用了相同的五元组而已)所错误的接收。在启用该配置,当一个socket连接进入TIME_WAIT状态后,内核里会记录包括该socket连接对应的五元组中的对方IP等在内的一些统计数据,当然也包括从该对方IP所接收到的最近的一次数据包时间。当有新的数据包到达,只要时间晚于内核记录的这个时间,数据包都会被统统的丢掉。

    这个配置,依赖于连接双方对timestamps的支持。同时,这个配置,主要影响到了inbound的连接(对outbound的连接也有影响,但是不是复用),即做为服务端角色,客户端连进来,服务端主动关闭了连接,TIME_WAIT状态的socket处于服务端,服务端快速的回收该状态的连接。

    5.close_wait产生原因

    比如是客户端要与服务端断开连接,先发一个FIN表示自己要主动断开连接了,服务端会先回一个ACK,这时表示客户端没数据要发了,但有可能服务端数据还没发完,所以要经历一个close_wait,等待服务端数据发送完,再回一个FIN和ACK。

    6.close_wait产生太多原因:

    close_wait 按照正常操作的话应该很短暂的一个状态,接收到客户端的fin包并且回复客户端ack之后,会继续发送FIN包告知客户端关闭关闭连接,之后迁移到Last_ACK状态。但是close_wait过多只能说明没有迁移到Last_ACK,也就是服务端是否发送FIN包,只有发送FIN包才会发生迁移,所以问题定位在是否发送FIN包。FIN包的底层实现其实就是调用socket的close方法,这里的问题出在没有执行close方法。说明服务端socket忙于读写。

    7.close_wait太多解决方法:

    方法1:代码层面做到

    第一:使用完socket就调用close方法;

    第二:socket读控制,当读取的长度为0时(读到结尾),立即close;

    第三:如果read返回-1,出现错误,检查error返回码,有三种情况:INTR(被中断,可以继续读取),WOULDBLOCK(表示当前socket_fd文件描述符是非阻塞的,但是现在被阻塞了),AGAIN(表示现在没有数据稍后重新读取)。如果不是AGAIN,立即close

    方法2:可以设置TCP的连接时长keep_alive_time还有tcp监控连接的频率以及连接没有活动多长时间被迫断开连接

    8.Socket连接到底是个什么概念?

    经常提socket,那么,到底什么是一个socket?其实,socket就是一个 五元组,包括:

    1. 源IP
    2. 源端口
    3. 目的IP
    4. 目的端口
    5. 类型:TCP or UDP

    9.什么时候用长连接,短连接?

    • 长连接

    连接->传输数据->保持连接 -> 传输数据-> ......->关闭连接。

    长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差。

    长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,再处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。

    • 短连接

    连接->传输数据->关闭连接

    HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。也可以这样说:短连接是指SOCKET连接后发送后接收完数据后马上断开连接。

    而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。

    总之,长连接和短连接的选择要视情况而定。

    10.报文发送接收方式 (同步和异步)?

    • 异步

    报文发送和接收是分开的,相互独立的,互不影响。这种方式又分两种情况:

    (1)异步双工:接收和发送在同一个程序中,由两个不同的子进程分别负责发送和接收

    (2)异步单工:接收和发送是用两个不同的程序来完成。

    • 同步

    报文发送和接收是同步进行,既报文发送后等待接收返回报文。

    同步方式一般需要考虑超时问题,即报文发出去后不能无限等待,需要设定超时时间,超过该时间发送方不再等待读返回报文,直接通知超时返回。

    在长连接中一般是没有条件能够判断读写什么时候结束,所以必须要加长度报文头。读函数先是读取报文头的长度,再根据这个长度去读相应长度的报文。

     

    展开全文
  • LINUX 大量TIME_WAIT状态的连接解决方法
  • time_wait产生原因: time_wait过多产生原因: time_wait过多解决方法: 短连接 长连接 close_wait产生原因: close_wait产生太多原因: close_wait太多解决方法: Socket连接到底是个什么概念? 什么时候...

    目录

    由于socket是全双工的工作模式,一个socket的关闭,是需要四次握手来完成的。

     time_wait 产生原因:

    time_wait过多产生原因:

    time_wait过多解决方法:

    短连接 

    长连接 

    close_wait产生原因:

    close_wait产生太多原因:

    close_wait太多解决方法:

    Socket连接到底是个什么概念?

    什么时候用长连接,短连接? 

    报文发送接收方式 (同步和异步)?


    由于socket是全双工的工作模式,一个socket的关闭,是需要四次握手来完成的。

    • 主动关闭连接的一方,调用close();协议层发送FIN包

    • 被动关闭的一方收到FIN包后,协议层回复ACK;然后被动关闭的一方,进入CLOSE_WAIT状态,主动关闭的一方等待对方关闭,则进入FIN_WAIT_2状态;此时,主动关闭的一方 等待 被动关闭一方的应用程序,调用close操作。

    • 被动关闭的一方在完成所有数据发送后,调用close()操作;此时,协议层发送FIN包给主动关闭的一方,等待对方的ACK,被动关闭的一方进入LAST_ACK状态;

    • 主动关闭的一方收到FIN包,协议层回复ACK;此时,主动关闭连接的一方,进入TIME_WAIT状态;而被动关闭的一方,进入CLOSED状态

    • 等待2MSL时间,如没发现重传的FIN,主动关闭的一方,结束TIME_WAIT,进入CLOSED状态

     time_wait 产生原因(等待2MSL意义):

    假设是客户端向服务端发起断开连接

    为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传这个FIN-ACK,接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。

    防止“已失效的连接请求报文段”出现在本连接中。

    客户端在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。

    time_wait过多产生原因:

    正常的TCP客户端连接在关闭后,会进入一个TIME_WAIT的状态,持续的时间一般在1-4分钟,对于连接数不高的场景,1-4分钟其实并不长,对系统也不会有什么影响,
    但如果短时间内(例如1s内)进行大量的短连接,则可能出现这样一种情况:客户端所在的操作系统的socket端口和文件描述符被用尽,系统无法再发起新的连接!

    举例来说:
      假设每秒建立了1000个短连接(Web场景下是很常见的,例如每个请求都去访问memcached),假设TIME_WAIT的时间是1分钟,则1分钟内需要建立6W个短连接,由于TIME_WAIT时间是1分钟,这些短连接1分钟内都处于TIME_WAIT状态,都不会释放,而Linux默认的本地端口范围配置是:net.ipv4.ip_local_port_range = 32768 61000不到3W,因此这种情况下新的请求由于没有本地端口就不能建立了。

    time_wait过多解决方法:

    1.可以改为长连接,但代价较大,长连接太多会导致服务器性能问题并且安全性也较差;
    2.修改ipv4.ip_local_port_range,增大可用端口范围,但只能缓解问题,不能根本解决问题;

    3.客户端机器打开tcp_tw_reuse和tcp_timestamps选项;

    字面意思,reuse TIME_WAIT状态的连接。时刻记住一条socket连接,就是那个五元组,出现TIME_WAIT状态的连接,一定出现在主动关闭连接的一方。所以,当主动关闭连接的一方,再次向对方发起连接请求的时候(例如,客户端关闭连接,客户端再次连接服务端,此时可以复用了;负载均衡服务器,主动关闭后端的连接,当有新的HTTP请求,负载均衡服务器再次连接后端服务器,此时也可以复用),可以复用TIME_WAIT状态的连接。

    通过字面解释,以及例子说明,你看到了,tcp_tw_reuse应用的场景:某一方,需要不断的通过“短连接”连接其他服务器,总是自己先关闭连接(TIME_WAIT在自己这方),关闭后又不断的重新连接对方。

    那么,当连接被复用了之后,延迟或者重发的数据包到达,新的连接怎么判断,到达的数据是属于复用后的连接,还是复用前的连接呢?那就需要依赖前面提到的两个时间字段了。复用连接后,这条连接的时间被更新为当前的时间,当延迟的数据达到,延迟数据的时间是小于新连接的时间,所以,内核可以通过时间判断出,延迟的数据可以安全的丢弃掉了。

    这个配置,依赖于连接双方,同时对timestamps的支持。同时,这个配置,仅仅影响outbound连接,即做为客户端的角色,连接服务端[connect(dest_ip, dest_port)]时复用TIME_WAIT的socket。

    4.客户端机器打开tcp_tw_recycle和tcp_timestamps选项;

    字面意思,销毁掉 TIME_WAIT。  

    当开启了这个配置后,内核会快速的回收处于TIME_WAIT状态的socket连接。多快?不再是2MSL,而是一个RTO(retransmission timeout,数据包重传的timeout时间)的时间,这个时间根据RTT动态计算出来,但是远小于2MSL。

        有了这个配置,还是需要保障 丢失重传或者延迟的数据包,不会被新的连接(注意,这里不再是复用了,而是之前处于TIME_WAIT状态的连接已经被destroy掉了,新的连接,刚好是和某一个被destroy掉的连接使用了相同的五元组而已)所错误的接收。在启用该配置,当一个socket连接进入TIME_WAIT状态后,内核里会记录包括该socket连接对应的五元组中的对方IP等在内的一些统计数据,当然也包括从该对方IP所接收到的最近的一次数据包时间。当有新的数据包到达,只要时间晚于内核记录的这个时间,数据包都会被统统的丢掉。

      这个配置,依赖于连接双方对timestamps的支持。同时,这个配置,主要影响到了inbound的连接(对outbound的连接也有影响,但是不是复用),即做为服务端角色,客户端连进来,服务端主动关闭了连接,TIME_WAIT状态的socket处于服务端,服务端快速的回收该状态的连接。

    短连接 


    连接->传输数据->关闭连接 
    HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。 
    也可以这样说:短连接是指SOCKET连接后发送后接收完数据后马上断开连接。  


    长连接 


    连接->传输数据->保持连接 -> 传输数据-> 。。。 ->关闭连接。 
    长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差。 

    close_wait产生原因:

    比如是客户端要与服务端断开连接,先发一个FIN表示自己要主动断开连接了,服务端会先回一个ACK,这时表示客户端没数据要发了,但有可能服务端数据还没发完,所以要经历一个close_wait,等待服务端数据发送完,再回一个FIN和ACK。

    close_wait产生太多原因:

    close_wait 按照正常操作的话应该很短暂的一个状态,接收到客户端的fin包并且回复客户端ack之后,会继续发送FIN包告知客户端关闭关闭连接,之后迁移到Last_ACK状态。但是close_wait过多只能说明没有迁移到Last_ACK,也就是服务端是否发送FIN包,只有发送FIN包才会发生迁移,所以问题定位在是否发送FIN包。FIN包的底层实现其实就是调用socket的close方法,这里的问题出在没有执行close方法。说明服务端socket忙于读写。

    close_wait太多解决方法:

    代码层面做到
    第一:使用完socket就调用close方法;
    第二:socket读控制,当读取的长度为0时(读到结尾),立即close;
    第三:如果read返回-1,出现错误,检查error返回码,有三种情况:INTR(被中断,可以继续读取),WOULDBLOCK(表示当前socket_fd文件描述符是非阻塞的,但是现在被阻塞了),AGAIN(表示现在没有数据稍后重新读取)。如果不是AGAIN,立即close
    可以设置TCP的连接时长keep_alive_time还有tcp监控连接的频率以及连接没有活动多长时间被迫断开连接

    Socket连接到底是个什么概念?

    经常提socket,那么,到底什么是一个socket?其实,socket就是一个 五元组,包括:

    1. 源IP

    2. 源端口

    3. 目的IP

    4. 目的端口

    5. 类型:TCP or UDP

    什么时候用长连接,短连接? 


     长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况,。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。 
      
    而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。 
      
    总之,长连接和短连接的选择要视情况而定。 


    报文发送接收方式 (同步和异步)?


    1、异步 
    报文发送和接收是分开的,相互独立的,互不影响。这种方式又分两种情况: 
    (1)异步双工:接收和发送在同一个程序中,由两个不同的子进程分别负责发送和接收 
    (2)异步单工:接收和发送是用两个不同的程序来完成。 
    2、同步 
    报文发送和接收是同步进行,既报文发送后等待接收返回报文。 同步方式一般需要考虑超时问题,即报文发出去后不能无限等待,需要设定超时时间,超过该时间发送方不再等待读返回报文,直接通知超时返回。 
    在长连接中一般是没有条件能够判断读写什么时候结束,所以必须要加长度报文头。读函数先是读取报文头的长度,再根据这个长度去读相应长度的报文。 
     

    展开全文
  • TIME_WAIT状态总结

    千次阅读 2022-03-20 22:02:23
    一:TIME_WAIT状态是什么 首先,这个是TCP状态转换图里面的某个状态。这个可以参考unix网络编程。 从图中可以看出,在一个客户端与服务器通信的过程当中,主动关闭的一方会进入这个状态。 二:TIME_WAIT状态怎么...

    这个知识点在写代码上,感觉还是挺重要的,打算总结一下吧。
    打算从以下5个方面去总结。
    一:TIME_WAIT状态是什么
    首先,这个是TCP状态转换图里面的某个状态。这个可以参考unix网络编程。
    在这里插入图片描述
    从图中可以看出,在一个客户端与服务器通信的过程当中,主动关闭的一方会进入这个状态。
    二:TIME_WAIT状态怎么出现的
    好了,其实第一点已经说明了,这个状态是怎么出现的了,就是,主动关闭的一方会进入这个状态。

    #include <stdio.h>
    #include <ctype.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    
    #define SERV_PORT 9000  //本服务器要监听的端口号,一般1024以下的端口很多都是属于周知端口,所以我们一般采用1024之后的数字做端口号
    
    int main(int argc, char *const *argv)
    {    
        //这些演示代码的写法都是固定套路,一般都这么写
    
        //服务器的socket套接字【文件描述符】
        int listenfd = socket(AF_INET, SOCK_STREAM, 0);    //创建服务器的socket,大家可以暂时不用管这里的参数是什么,知道这个函数大概做什么就行
    
        struct sockaddr_in serv_addr;                  //服务器的地址结构体
        memset(&serv_addr,0,sizeof(serv_addr));
        
        //设置本服务器要监听的地址和端口,这样客户端才能连接到该地址和端口并发送数据
        serv_addr.sin_family = AF_INET;                //选择协议族为IPV4
        serv_addr.sin_port = htons(SERV_PORT);         //绑定我们自定义的端口号,客户端程序和我们服务器程序通讯时,就要往这个端口连接和传送数据
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); //监听本地所有的IP地址;INADDR_ANY表示的是一个服务器上所有的网卡(服务器可能不止一个网卡)多个本地ip地址都进行绑定端口号,进行侦听。
    
        int result;
        result = bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));//绑定服务器地址结构体
        if(result  == -1)
        {
            char *perrorinfo = strerror(errno); 
            printf("bind返回的值为%d,错误码为:%d,错误信息为:%s;\n",result,errno,perrorinfo);
            return -1;
        }
        result = listen(listenfd, 32);     //参数2表示服务器可以积压的未处理完的连入请求总个数,客户端来一个未连入的请求,请求数+1,连入请求完成,c/s之间进入正常通讯后,请求数-1
        if(result == -1)
        {        
            char *perrorinfo = strerror(errno); 
            printf("listen返回的值为%d,错误码为:%d,错误信息为:%s;\n",result,errno,perrorinfo);
            return -1;
        }
    
        int connfd;
        const char *pcontent = "I sent sth to client!\n"; //指向常量字符串区的指针
        for(;;)
        {
            //卡在这里,等客户单连接,客户端连入后,该函数走下去【注意这里返回的是一个新的socket——connfd,后续本服务器就用connfd和客户端之间收发数据,而原有的lisenfd依旧用于继续监听其他连接】        
            connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
    
            //发送数据包给客户端
            write(connfd,pcontent,strlen(pcontent)); //注意第一个参数是accept返回的connfd套接字
            printf("本服务器给客户端发送了一串字符~~~~~~~~~~~!\n");
            
            //只给客户端发送一个信息,然后直接关闭套接字连接;
            close(connfd); 
        } //end for
        close(listenfd);     //实际本简单范例走不到这里,这句暂时看起来没啥用
        return 0;
    }
    

    使用以上程序作为服务端,然后用telnet作为客户端,发起连接,这个时候,根据程序说明,会马上关闭这个连接,然后,我们用netstat命令观察可以看到除了有一个端口处于监听状态意外,还有的就是出现了TIME_WAIT这个状态了。
    三:TIME_WAIT状态出现了有什么影响
    感觉第二点出现的情况,如果我们马上关闭这个服务端程序,然后又重新启动,这个时候你会发现这个程序启动失败失败的原因是bind error了,提示地址已复用,也就是同一个地址和端口只能同时绑定一次。我们试想,如果在服务端处理大量连接的时候,某个时候,服务端挂掉了,这个时候由于TIME_WAIT状态的存在,导致程序运行不起来,那不坏菜了,服务端还怎么提供服务??
    四:为什么要有TIME_WAIT状态
    我们再来谈谈为什么需要这个状态?什么,居然要有这个状态??第三点不是说有这个状态会有不好的情况吗?当然,先别急,既然这个状态的出现就有他出现的道理,对于第三点出现时会有一些影响,当然,我们也是可以避免的,我们在第五点去谈这个问题。

    为什么要有这个状态,参考了unix网络编程当中谈到的两点。
    一::可靠地实现TCP全双工的终止。
    在这里插入图片描述

    这句话怎么理解呢?我们知道tcp是全双工的,
    我们看上面的图,在左边,
    如果没有TIME_WAIT这个状态,
    那么服务端便会从FIN_WAIT2这个状态->CLOSED状态,
    这两个状态的转变有什么影响吗?我们看上图,
    如果服务端最后一次发送的ack包,
    由于某种原因丢了,客户端没有收到,
    那么根据tcp的特性,客户端会再次发送FIN包,
    如果此时服务端处于TIME_WAIT状态,
    就会重发这个ack包,如果此时服务端处于CLOSED状态,
    无论客户端有没有收到ack包,
    因为这个连接已经关闭了,所以服务端也就不会重发最
    后一个ack包了,这种断开就是不太友好的,
    如果有了TIME_WAIT状态,那么便有助于可靠
    的实现TCP全双工连接的终止。
    

    二:允许老的重复的TCP数据包在网络中消逝(丢弃)。

    怎么理解这句话呢?这个要结合TIME_WAIT
    为什么要存在的时间是1-4min有关了,
    根据资料说明,一个数据包在网络上存
    活的时间大概是1-4min,我们还是从反
    面来想这个问题,如果没有这个状态,
    那么在服务端发送最后一次ack包以后,
    服务端会马上处于CLOSE状态,然后,
    假设这个时候有一个新的客户端连进来,
    假设这个新的客户端的IP,PORT与之前
    的一个客户端是一样的,没有TIME_WAIT状态,
    最后一个ack的包可能就会发到这个新的连接
    上来。。。。。。如果有TIME_WAIT状态,
    即使有人伪造一个相同IP和PORT的连接,
    也不会让这个包发到刚刚建立起来的连接上。
    

    五:如何避免TIME_WAIT状态
    使用套接字选项可以避免这个状态的产生,从而可以让服务端程序在出现异常时可以快速的重启,恢复运行。
    setsockopt,这个函数一般位于socket与bind之间,如果想探讨为什么一般位于这两个函数之间的,可以网上搜索。

    #include <stdio.h>
    #include <ctype.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    
    #define SERV_PORT 9000  //本服务器要监听的端口号,一般1024以下的端口很多都是属于周知端口,所以我们一般采用1024之后的数字做端口号
    
    int main(int argc, char *const *argv)
    {    
        //这些演示代码的写法都是固定套路,一般都这么写
    
        //服务器的socket套接字【文件描述符】
        int listenfd = socket(AF_INET, SOCK_STREAM, 0);    //创建服务器的socket,大家可以暂时不用管这里的参数是什么,知道这个函数大概做什么就行
    
        struct sockaddr_in serv_addr;                  //服务器的地址结构体
        memset(&serv_addr,0,sizeof(serv_addr));
        
        //设置本服务器要监听的地址和端口,这样客户端才能连接到该地址和端口并发送数据
        serv_addr.sin_family = AF_INET;                //选择协议族为IPV4
        serv_addr.sin_port = htons(SERV_PORT);         //绑定我们自定义的端口号,客户端程序和我们服务器程序通讯时,就要往这个端口连接和传送数据
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); //监听本地所有的IP地址;INADDR_ANY表示的是一个服务器上所有的网卡(服务器可能不止一个网卡)多个本地ip地址都进行绑定端口号,进行侦听。
    
    
        //setsockopt():设置一些套接字参数选项;
        //参数2:是表示级别,和参数3配套使用,也就是说,参数3如果确定了,参数2就确定了;
        //参数3:允许重用本地地址
        int  reuseaddr=1; //开启
        if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR, (const void *) &reuseaddr,sizeof(reuseaddr)) == -1)
        {
             char *perrorinfo = strerror(errno); 
            printf("setsockopt(SO_REUSEADDR)返回值为%d,错误码为:%d,错误信息为:%s;\n",-1,errno,perrorinfo);
        }
    
        int result;
        result = bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));//绑定服务器地址结构体
        if(result  == -1)
        {
            char *perrorinfo = strerror(errno); 
            printf("bind返回的值为%d,错误码为:%d,错误信息为:%s;\n",result,errno,perrorinfo);
            return -1;
        }
        result = listen(listenfd, 32);     //参数2表示服务器可以积压的未处理完的连入请求总个数,客户端来一个未连入的请求,请求数+1,连入请求完成,c/s之间进入正常通讯后,请求数-1
        if(result == -1)
        {        
            char *perrorinfo = strerror(errno); 
            printf("listen返回的值为%d,错误码为:%d,错误信息为:%s;\n",result,errno,perrorinfo);
            return -1;
        }
        int connfd;
        const char *pcontent = "I sent sth to client!\n"; //指向常量字符串区的指针
        for(;;)
        {
            //卡在这里,等客户单连接,客户端连入后,该函数走下去【注意这里返回的是一个新的socket——connfd,后续本服务器就用connfd和客户端之间收发数据,而原有的lisenfd依旧用于继续监听其他连接】        
            connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
    
            //发送数据包给客户端
            write(connfd,pcontent,strlen(pcontent)); //注意第一个参数是accept返回的connfd套接字
            printf("本服务器给客户端发送了一串字符~~~~~~~~~~~!\n");
            
            //只给客户端发送一个信息,然后直接关闭套接字连接;
            close(connfd); 
        } //end for
        close(listenfd);     //实际本简单范例走不到这里,这句暂时看起来没啥用
        return 0;
    }
    

    可以使用以上程序配合telnet进行测试。

    展开全文
  • 解决mysql出现大量TIME_WAIT
  • 主动发起关闭连接的一方,才会有 TIME-WAIT 状态。 需要 TIME-WAIT 状态,主要是两个原因: 防止具有相同「四元组」的「旧」数据包被收到; 保证「被动关闭连接」的⼀方能被正确的关闭,即保证最后的 ACK 能让...
  • 解决进程的time_wait状态 查看进程连接状态 #netstat -an|awk ‘/tcp/ {print $6}’|sort|uniq -c 16 CLOSING 130 ESTABLISHED 298 FIN_WAIT1 13 FIN_WAIT2 9 LAST_ACK 7 LISTEN 103 SYN_RECV 5204 TIME_WAIT 状...
  • 今天登陆服务器想查看一个端口的占用情况,...time_wait的作用 1 2 3 4 5 6 7 8 9 10 TIME_WAIT状态存在的理由: 1)可靠地实现TCP全双工连接的终止 ...
  • tcp_fin_timeout:主动关闭方TCP保持在FIN_WAIT_2状态的时间。对方可能会一直不结束连接或不可预料的进程死亡。默认值为60秒。 修改方法: sysctl -w ...
  • struct tcp_timewait_sock { struct inet_timewait_sock tw_sk; u32 tw_rcv_nxt; u32 tw_snd_nxt; u32 tw_rcv_wnd; u32 tw_ts_offset; u32 tw_ts_recent; long tw_ts_recent_stamp; }; struct inet_timewait_sock...
  • time_wait 处理方法

    千次阅读 2022-03-18 16:17:46
    Socket中的TIME_WAIT状态 在高并发短连接的server端,当server处理完client的请求后立刻closesocket此时会出现time_wait状态然后如果client再并发2000个连接,此时部分连接就连接不上了,用linger强制关闭可以解决此...
  • 记一次TIME_WAIT过多导致的服务异常

    千次阅读 2021-12-16 02:40:02
    文章目录前言排查问题为什么会有这么多TIME-WAIT呢?我们先来回忆一下TCP四次挥手的过程阻止延迟数据段保证连接被关闭开始解决问题方案1方案2总结 前言 前几天萌新遇到了一个问题,客户购买了我们的产品以后,发现...
  • 一、服务器有大量TIME_WAIT状态 1.1 原因 一些爬虫服务器或者WEB服务器(如果在安装的时候没有做内核参数优化的话)上经常会遇到这个问题。 对于基于TCP的HTTP协议,关闭TCP连接的是Server端,这样,Server端会...
  • 书上说,处于 TIME_WAIT 状态的连接,在收到相同四元组的 SYN 后,会回 RST 报文,对方收到后就会断开连接。 书中作者只是提了这么一句话,没有给予源码或者抓包图的证据。 起初,我看到也觉得这个逻辑也挺符合常理...
  • 从Linux源码看TIME_WAIT状态的持续时间 前言 笔者一直以为在Linux下TIME_WAIT状态的Socket持续状态是60s左右。线上实际却存在TIME_WAIT超过100s的Socket。由于这牵涉到最近出现的一个复杂Bug的分析。所以,笔者就...
  • 【Linux网络编程】你了解TIME_WAIT状态吗? 从这幅状态图中可以看到,通信双方建立TCP连接后,在发生四次挥手之后,先发FIN标志位的一端就会进入time_wait状态,换句话说,主动关闭连接的一方就会进入TIME_WAIT...
  • 大量的TIME_WAIT netstat ss -s netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}' RFC 793协议中给出的建议是两分钟,不过实际上不同的操作系统可能有不同的设置,...
  • netstat查看系统TIME_WAIT状态个数

    千次阅读 2020-06-08 22:06:17
    netstat-n|awk'/^tcp/{++S[$NF]}END{for(ainS)printa,S...常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭。 具体每种状态什么意思,其实无需多说,看看下面这种...
  • TCP中time_wait解释及解决方法

    千次阅读 2021-07-28 11:50:45
    总的来说,主动关闭连接的一方才会进入TIME_WAIT状态。 客户端主动关闭连接时,会发送最后一个ack后,然后会进入TIME_WAIT状态,再停留2个MSL时间,进入CLOSED状态 MSL时间 MSL就是maximum segment lifetime...
  • 文章目录存在close_wait的原因和解决办法存在FIN_WAIT2的原因和解决办法存在TIME_WAIT的原因和解决办法处理这类问题的实用命令 存在close_wait的原因和解决办法 close_wait这个状态存在于服务端,当服务端发送FIN...
  • TCP协议中的TIME_WAIT详细说明

    千次阅读 2020-04-26 11:38:43
    文章目录4.3设置TIME_WAIT状态的目的4.3.1 实现TCP全双工连接的关闭4.3.2 使过时的重复报文段失效4.3.3 TIME_WAIT状态的自结束4.3.4 TIME_WAIT状态的影响(补充) 4.3设置TIME_WAIT状态的目的 TIME_WAIT状态是TCP中...
  • 解决Linux TIME_WAIT过多造成的问题

    万次阅读 多人点赞 2019-04-15 21:23:35
    1、 time_wait的作用: TIME_WAIT状态存在的理由: 1)可靠地实现TCP全双工连接的终止 在进行关闭连接四次挥手协议时,最后的ACK是由主动关闭端发出的,如果这个最终的ACK丢失,服务器将重发最终的FIN, 因此...
  • B收到FIN包后,回复ACK,进入CLOSE_WAIT状态,A等待对方关闭,进入FIN_WAIT_2状态,此时,A会等待B的应用程序调用close操作 B在完成所有数据发送后,调用close()操作;此时,协议层会发送FIN包给A,然后等待对方的...
  • 写在开头,大概 4 年前,听到运维同学提到 TIME_WAIT 状态的 TCP 连接过多的问题,但是当时没有去细琢磨;最近又听人说起,是一个新手进行压测过程中,遇到的问题,因此,花点时间...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 535,228
精华内容 214,091
关键字:

time_wait

友情链接: 1_your ride is here.rar