前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TCP四次挥手和TIME_WAIT

TCP四次挥手和TIME_WAIT

作者头像
全栈程序员站长
发布2022-08-25 14:07:26
4870
发布2022-08-25 14:07:26
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

TCP四次挥手和TIME_WAIT
TCP四次挥手和TIME_WAIT
TCP四次挥手和TIME_WAIT
TCP四次挥手和TIME_WAIT

FIN_WAIT_1 : FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是: FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。(主动方)

FIN_WAIT_2 :实际上FIN_WAIT_2状态下的SOCKET,表示半连接 ,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。

TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文 ,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。(主动方)

CLOSING(比较少见) : 这种状态比较特殊,实际情况中应该是很少见。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。

CLOSE_WAIT : 表示在等待关闭。当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。

LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。

CLOSED: 表示连接中断。

同时关闭

TCP四次挥手和TIME_WAIT
TCP四次挥手和TIME_WAIT

为什么需要四次挥手?

那可能有人会有疑问,在tcp连接握手时为何ACK是和SYN一起发送,这里ACK却没有和FIN一起发送呢。原因是因为tcp是全双工模式,接收到FIN时意味将没有数据再发来,但是还是可以继续发送数据(解决全双工问题)。

TIME_WAIT

TIME_WAIT状态会持续2MSL的时间才会转换到CLOSE状态,一般是1-4分钟(现在对于linux是30秒)。MSL(最大分段生存期):指明TCP报文在Internet上最长生存时间。

只有主动关闭的一方才会进入TIME_WAIT状态。那么端口不够用就是文件描述符不够用了,因为文件描述符只有在从TIME_WAIT状态转换到CLOSE状态后才会真正被系统收回。

问题

TCP四次挥手和TIME_WAIT
TCP四次挥手和TIME_WAIT

如果执行主动关闭的一方HOST1不进入到TIME_WAIT状态就关闭连接那会发生什么呢?

当重传的FIN消息到达时,因为TCP已经不再有连接的信息了,所以就用RST(重新启动)消息应答,导致HOST2进入错误的状态而不是有序终止状态(如果主动关闭的一方又开启了一个新的链接,则重发的FIN会将新连接给关闭掉),如果发送最后ACK消息的一方HOST1处于TIME_WAIT状态并仍然记录着连接的信息,它就可以正确的响应HOST2的FIN消息了。(最后一个ACK可能丢失并导致HOST2重新发送FIN消息,导致老连接的包会干扰新连接

TIME_WAIT占用的资源

1、TW会占用内存,但是占用内存很小(1W的TW连接占用1M左右)

2、对CPU也是有影响的,比如TW的端口太多,导致选择可用端口时,需要很多次选择才能成功;但这个影响也是很小的。

3、TW连接会占用大量端口。

4、被占用的是一个五元组:(协议,本地IP,本地端口,远程IP,远程端口)。对于Web 服务器,协议是TCP,本地IP通常也只有一个,本地端口默认的80或者443。只剩下远程 IP和远程端口可以变了。如果远程IP相同的话,就只有远程端口可以变了。这个只有几万个(net.ipv4.ip_local_port_range),所以当同一客户端向服务器建立了大量连接之后,会耗尽可用的五元组导致问题。

https://www.zhihu.com/question/29354418?sort=created

http://www.cnblogs.com/lulu/p/4149312.html

TIME_WAIT优化

tcp_timestamps

只有该选项开启了,tcp_tw_reuse和tcp_tw_recycle才能起作用。另外tcp_timestamps可以解决PAWS和计算RTT的问题。

tcp_tw_reuse

需要开启tcp_timestamps时才有效。针对于一个连接,如果开启了该开关,即便该连接处于TW状态,收到SYN包之后,也能建立一条新的连接。该连接跟之前的TW连接5元组相同。但是需要满足下面条件的其中一个:

1)初始化序列号比老的TW序列号大。

2)新来的连接的时间戳比老的TW的时间戳大。

tcp_tw_recycle

快速回收TW,应该是RTO时间内回收。需要开启tcp_timestamps时才有效。

即使快速回收之后,也保留了一些信息,保留的信息有:对端IP、最后的对端过来的时间戳等。对于新来的连接,同时满足下面3个条件时,连接会被拒绝;否则连接不会被拒绝:

1)来自该IP的TCP连接请求带有时间戳信息;

2)在MSL时间内,收到过该IP过来的数据;

3)新连接的时间戳小于保存的TW的时间戳;

tcp_max_tw_buckets

这个是控制并发的TIME_WAIT的数量,默认值是50几W,如果超限,那么,系统会把多的给destory掉,然后在日志里打一个警告。

SO_LINGER

struct linger {

int l_onoff; /* 0 = off, nozero = on */

int l_linger; /* linger time */

};

1)设置 l_onoff为0,则该选项关闭,l_linger的值被忽略,等于内核缺省情况,close调用会立即返回给调用者,如果可能将会传输任何未发送的数据。

2)设置 l_onoff为非0,l_linger为0,则套接口关闭时TCP夭折连接,TCP将丢弃保留在套接口发送缓冲区中的任何数据并发送一个RST给对方,而不是通常的四分组终止序列,这避免了TIME_WAIT状态;(说明如果没有数据被丢弃,也是正常的四次挥手;不是rst)

3)设置 l_onoff 为非0,l_linger为非0,当套接口关闭时内核将拖延一段时间(由l_linger决定)。

TCP关闭连接的方式

正常关闭

调用close()关闭socket、没close但进程正常结束(当然这是不应该的做法)、进程core掉、在shell 命令行中kill掉进程,都可抽象成“正常”关闭。因为即使core掉,内核也会马上帮应用程序回收(close)socket文件描述符。

不正常关闭

客户端崩溃了,此时肯定发不出FIN包了(当然啦,内核都没机会帮应用程序回收资源了)。这种情况,服务器端有如下两种情况。

1、服务器send数据,因为客户端已经崩溃,服务器收不到ACK自然会不停的重传。Berkeley的重传机制,重传8次,相对第一次传的15分钟后仍没收到ACK,则返回ETIMEDOUT或EHOSTUNREAC错误。如果服务器不理会这个错误,再次调用send,则立马返回Broken Pipe错误。

2、服务器不发任何数据了,那只有靠应用层心跳检测机制或Keepalive,来发觉TCP断连了。

参考资料

https://zhuanlan.zhihu.com/p/29334504

https://zhuanlan.zhihu.com/p/32386693

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/142632.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年5月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么需要四次挥手?
  • TIME_WAIT
    • 问题
      • TIME_WAIT占用的资源
      • TIME_WAIT优化
        • tcp_timestamps
          • tcp_tw_reuse
            • tcp_tw_recycle
              • tcp_max_tw_buckets
              • SO_LINGER
              • TCP关闭连接的方式
                • 正常关闭
                  • 不正常关闭
                    • 参考资料
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档