是否由于关闭连接启动器而导致FIN_WAIT2状态?

时间:2018-05-15 14:14:56

标签: sockets posix tcp-ip netstat

我正在做一些POSIX套接字编程并遇到了问题。我写了一个使用非阻塞套接字的应用程序。因为我正在针对正在开发的服务器开发客户端,所以偶尔会发送错误的应用程序级别的消息。当发生这种情况时,我唯一的恢复方法是完全重新建立连接以强制通信进入已知状态。

我通过在非阻塞套接字上发出POSIX“close()”来重置连接。然后我请求一个新的套接字并重新建立连接。

然而,我发现的一件事是所有重置导致旧连接上的“FIN_WAIT2”。运行netstat命令时,有大量的FIN_WAIT2没有与之关联的PID(我猜这些被认为是孤立的,可以尝试内核连接超时?)。

无论如何,我很好奇为什么所有这些旧连接都堆叠在netstat中。我已经对TCP状态进行了一些阅读,似乎我看到的FIN_WAIT2是由于服务器(即在我的情况下不是关闭发起者)没有响应它成功关闭的消息。这是为什么?

FIN_WAIT2通常与非关闭发起方的错误相关联吗?或者我是否有可能在我的应用程序中执行某些操作来阻止FIN消息被接收?我使用非阻塞套接字的事实是否与它有关?

1 个答案:

答案 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状态图:

TCP State Diagram