TCP关闭连接 - 不容易

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TCP关闭连接 - 不容易相关的知识,希望对你有一定的参考价值。

参考技术A

(1) 收到rst后,内核会立马释放该TCP连接所占用的内存资源(状态、数据)、以及端口号。
(2) 收到rst后,应用层首次读,read返回-1,并设置errno为ECONNRESET。POLLIN 会立刻再次触发,再read会返回0。
(3) 收到rst后,应用层首次写,(此时写操作返回EPIPE错误)内核向该进程发送一个SIGPIPE信号,该信号的默认行为是终止进程,因此进程必须捕获它以免不情愿地被终止。

对于本端来讲,关闭一个TCP连接只有两种情况:
(1)RST,相当于重置了。
(2)关掉本端写(即发送FIN分节),而无法主动关闭对端写,也就是只能主动关闭半个连接,另外一个方向连接的关闭是对端主动进行的。

(3)假如本端收到对端的FIN分节后(即read返回0),是无法判断对端究竟是close(对端也不读了)还是shutdown(对端还可以读,半关闭)。

Q : 那么此时,我们再去wirte会怎么样呢?
1、客户端可能调用shutdown(cfd, SHUT_WR),即单向关闭了它的写端,于是我read到0,这种情况我不想马上关闭这个连接,而是把给这个客户的回复都写完后再关闭。
2、客户端可能调用close(cfd)。这时我如果write(sfd, buf2,size2),就会返回EPIPE错误。

Q : 当read返回0后,该怎么办呢?
此时是否要close取决于你的应用。通常来说如果对方调用的是close,那么你也可以close。否则你不能close,例如对方发送一个包给你并shutdown write然后调用recv,这时候你还可以返回一个或多个包,连接此时处于半关闭状态,可以一直持续。 摘自 知乎 胡宇光

Q : FIN_WAIT2 和CLOSE_WAIT这两状态会一直持续下去么?

【参考】
https://www.yuque.com/infuq/others/yyvoa7#cDrZq
https://blog.csdn.net/huangyimo/article/details/81297805
https://blog.csdn.net/qq_35733751/article/details/80146161
【补充面试题】

1.如何避免TCP的TIME_WAIT状态(高并发)

以上是关于TCP关闭连接 - 不容易的主要内容,如果未能解决你的问题,请参考以下文章

如何模拟强制关闭的 TCP 连接?

tcp关闭状态详解

记一次排查mysql数据库连接未关闭问题的过程

c++ 服务器在客户端终止连接进程后不关闭 TCP 套接字连接

TCP三次握手(建立连接)/四次挥手(关闭连接)

TCP 端点如何知道另一个端点是关闭了连接的两半还是只关闭了一个?