TCP四次挥手
双方都可以主动关闭连接,调用 close()

- 客户端调用CLOSE主动关闭连接,此时会发送一个TCP首部的FIN标志位被置为1的报文,即FIN报文,之后客户端就会进入FIN_WAIT_1的状态
- 服务端接受到这个FIN报文后,会回一个ACK,并进入CLOSE_WAIT状态
- 客户端收到这个ACK后,会进入FIN_WAIT_2的状态
- 等待服务端处理好数据后(这时候TCP连接处于半连接半关闭状态,但还是可以互传数据),调用那个CLOSE函数,也向客户端发送FIN报文,之后服务端就会进入LAST_ACK 状态
- 客户端收到服务端的 FIN 报文后,回一个ACK,之后进入TIME_WAIT状态
- 服务端收到ACK后,进入CLOSE状态,即服务端这时候就已经关闭连接了
- 客户端等待2MSL秒后就自动进入CLOSE状态
为什么需要四次挥手
- 客户端发送FIN后,仅仅告诉服务端我不再发送数据了,但接受数据还是可以的
- 服务端接受到FIN后,会给客户端发一个ACK,而服务端可能还会有数据没发送,则等数据发完后才会给客户端发一个FIN,表示我也要关闭连接了
- 而客户端需要回复第四次挥手,服务端接受到后才知道对方连接额关闭了,不然服务端都不知道客户端是否接受到了第三次挥手,就无法正常关闭连接
服务端发送ACK后,需要等数据全部传输完再发送FIN,所以需要四次挥手的。但是在没有数据发送 且 开启了TCP延迟确认机制下(默认情况下),服务端的ACK和FIN是可以合并的,也就是只需要三次挥手的
TCP延迟确认机制:
- 当有
为什么要有TIME_WAIT?
主动发起关闭请求的一方,才会有TIME_WAIT状态
需要这个状态的原因:
- 防止历史中的数据,被后面相同四元组的连接误收,这个时间足以让数据在网络中丢失,再出现的数据包一定是新建立连接产生的
- 保证 被动关闭的一方,能被正确地关闭。等待足够的时间以确保最后的ack能让接收方接受到,从而帮助其正常优雅地关闭,即让客户端尽量把数据发完
为什么TIME_WAIT等待的时间是2MSL?
MSL:最大段生存期 ( MSL) 是指 TCP段在互联网络中可以存在的时间。1981 被定义为 2分钟。
最新的内核已经被优化为3.5s
为什么TCP4次挥手时等待为2MSL? - Gypsophila N的回答 - 知乎
https://www.zhihu.com/question/67013338/answer/1032098712
这个我觉得一个主要原因就是要保证此次TCP连接的所有报文都能在网络中消失,也就是避免前后两个使用相
同四元组的前一个TCP连接的报文干扰到后一个连接。
假设主动关闭方为A,被动关闭方为B
A发送ack后,这个ack最坏情况下MSL后到达B,此时B因为没收到ack,会根据ROT机制重传FIN,那么这个
FIN最坏会在1 MSL后消失。因此从A发送ack后,A就需要等待TimeWait 即 2MSL,来保证A发送的最后一个
ack和B发送的最后一个FIN可以在网络中消息

还有一点我看网上说还有就是保证被动关闭方能够接受到自己FIN的ack,我觉得这点是不对的。
假如现在 A 收到 FIN 之后,为了实现目标 1,即保证 B 能够收到自己的 ACK 报文。那么 A 完美的等待时间不是 2MSL,而应该是从 B 发送第一个 FIN 报文开始计时到它最后一次重传 FIN 报文这段时长加上 MSL。但这个计算方式过于保守,只有在所有的 ACK 报文都丢失的情况下才需要这么长的时间;另外,第一个目标虽然重要,但并不十分关键,因为既然已经到了关闭连接的最后一步,说明在这个 TCP 连接上的所有用户数据已经完成可靠传输,所以要不要完美的关闭这个连接其实已经不是那么关键了。因此,(我猜)RFC 标准的制定者才决定以网络丢包不太严重为前提条件,然后根据第二个目标来计算 TIME_WAIT 状态应该持续的时长。
TIME_WAIT过多会怎样?
1.占用系统资源,像fd,cpu,内存等等
2.占用端口资源,端口资源也是有限的,一般可以开启的端口为 32768~61000,当然我们可以设置
TIME_WAIT过多怎么办?
处于TIME-WAIT状态的TCP连接过多主要会导致三个问题。
第一个问题是资源占用过多的问题,包括端口号占用,内存占用等。
第二个问题是性能下降,包括系统负担加重,响应时间变长等。
第三个问题是连接问题,包括创建新连接可能失败,连接传输不稳定等。
而解决思路也有很多。
第一种思路是尽可能使用长连接和连接池,避免连接频繁创建和关闭。
第二种思路是调整 TIME_WAIT 的参数。
第三种思路是优化操作系统,例如说增大端口号范围,增大内存或者优化内存使用,以便可以支持更多的 TCP 连接。
但在实际场景中,我们一般都是利用谁主动关闭谁才有TIME_WAIT状态这个特性来避免,不让服务端主动关闭,而是浏览器或者客户端
服务端大量出现TIME_WAIT?
说明服务端主动断开了连接,只有主动关闭方才存在这个状态
一般有以下情况,属于正常的情况
1.HTTP短连接,即一个HTTP为一个TCP连接,不存在复用的情况
2.HTTP长连接超时
3.HTTP长连接的数量达到上限
双方同时断开连接?
如何判断是主动断开的连接,调用了close()函数
