我正在做一些POSIX套接字编程并遇到了问题。我写了一个使用非阻塞套接字的应用程序。因为我正在针对正在开发的服务器开发客户端,所以偶尔会发送错误的应用程序级别的消息。当发生这种情况时,我唯一的恢复方法是完全重新建立连接以强制通信进入已知状态。
我通过在非阻塞套接字上发出POSIX“close()”来重置连接。然后我请求一个新的套接字并重新建立连接。
然而,我发现的一件事是所有重置导致旧连接上的“FIN_WAIT2”。运行netstat命令时,有大量的FIN_WAIT2没有与之关联的PID(我猜这些被认为是孤立的,可以尝试内核连接超时?)。
无论如何,我很好奇为什么所有这些旧连接都堆叠在netstat中。我已经对TCP状态进行了一些阅读,似乎我看到的FIN_WAIT2是由于服务器(即在我的情况下不是关闭发起者)没有响应它成功关闭的消息。这是为什么?
FIN_WAIT2通常与非关闭发起方的错误相关联吗?或者我是否有可能在我的应用程序中执行某些操作来阻止FIN消息被接收?我使用非阻塞套接字的事实是否与它有关?
答案 0 :(得分:1)
总之,是的,您可能在非关闭发起方方面存在错误。它与非阻塞套接字无关。非阻塞套接字仅影响应用程序与其自己的操作系统之间的交互。
了解两个方必须终止套接字连接以便正确清理状态,这一点很重要。听起来你的服务器没有关闭套接字的结尾。一种可能的情况:
accept
connect
创建连接(双方的TCP状态转移到ESTABLISHED
send
/ recv
/ send
/ recv
/ etc(状态仍为ESTABLISHED
)close
;客户端操作系统向服务器发送FIN
数据包(客户端操作系统将套接字状态移至FIN_WAIT1
)ACK
以确认客户端计算机的FIN
(服务器操作系统将套接字状态移至CLOSE_WAIT
;客户端操作系统将套接字状态移至FIN_WAIT2
)FIN
,因此客户端操作系统会将套接字维持在FIN_WAIT2
状态。 (服务器套接字状态在CLOSE_WAIT
中说明)客户端套接字状态可能会长时间保持FIN_WAIT2
状态,甚至永远不会,这取决于操作系统的实现。例如,Linux有一个可调变量tcp_fin_timeout
,它指定一个空闲连接在FIN_WAIT2
中保留多长时间;但TCP标准没有为FIN_WAIT2
指定超时。 (请注意,客户端程序不知道任何此类。它已关闭套接字,套接字文件描述符已被破坏,套接字不再可访问;这全部由操作系统。)
如果发生了这种情况,您可以尝试重新启动服务器程序(因为当您终止服务器进程时,服务器的操作系统将自动关闭其所有打开的文件,这将导致FIN
被发送在任何仍然打开的插座上)。我想你会看到重新启动服务器会导致所有这些客户端套接字进入TIME_WAIT
状态,在这种状态下,它们将保持一段时间,然后自行消失。 (是为TIME_WAIT
指定的超时机制。)
另见TCP状态图: