4

希望有人可以帮助我们,因为我们正在调查可以去!

我们有一个用 C# 编写的简单异步套接字服务器,它接受来自 ASP.NET Web 应用程序的连接,发送消息,执行一些处理(通常针对 DB,但也针对其他系统),然后将响应发送回客户端. 客户端负责关闭连接。

我们一直遇到问题,如果系统在很长一段时间内(通常是几天)处于重负载状态,CLOSE_WAIT 套接字会在服务器盒(netstat -a)上建立,以至于进程不会接受任何进一步的连接. 在这一点上,我们必须反弹该过程并再次运行它。

我们已经尝试对我们的 ASP.NET 应用程序运行一些负载测试以尝试复制问题(因为无法从代码中推断出某些问题)。我们认为我们已经解决了这个问题,并最终得到了问题的 WireShark数据包跟踪,在套接字服务器的日志中显示为 SocketException:

System.Net.Sockets.SocketException:远程主机在 System.Net.Sockets.Socket.BeginSend(Byte[] 缓冲区,Int32 偏移量,Int32 大小,SocketFlags socketFlags,AsyncCallback 回调,对象状态)处强行关闭了现有连接

我试图从数据包跟踪中重现该问题,因为它是一个直接与套接字服务器对话的单线程进程(使用与 ASP.NET 应用程序相同的代码),但我无法做到。

有没有人对接下来要尝试、检查的事情或我们可能做错的明显事情有任何建议?

4

6 回答 6

6

看图

http://en.wikipedia.org/wiki/File:Tcp_state_diagram_fixed.svg

您的客户端通过调用 close() 关闭了连接,这将 FIN 发送到服务器套接字,服务器套接字确认了 FIN 并且其状态现在更改为 CLOSE_WAIT,并保持这种状态,除非服务器在该套接字上发出 close() 调用。

您的服务器程序需要检测客户端是否中止了连接,然后立即 close() 以释放端口。如何?请参阅读取()。在读取文件结尾(意味着收到 FIN)时,返回零。

于 2009-03-25T23:18:41.773 回答
5

如果您的服务器正在累积CLOSE_WAIT套接字,则连接完成时它不会关闭其套接字。如果您查看 Chris 帖子评论中的状态图,您会看到一旦套接字关闭并已发送,就会CLOSE_WAIT转换为。LAST_ACKFIN

您说由于异步性质而确​​定在哪里执行此操作很复杂?这应该不是问题,如果您的 recv 的回调返回 0 字节,您应该关闭套接字(假设一旦您的客户端关闭其一侧的连接,您就无事可做)。如果您确实需要担心继续发送,请在此处执行 Shutdown(recv) 并记下您的客户端已关闭,一旦您完成发送,请执行 Shutdown(send) 和 Close。

您可能会在读取的回调中发出新的读取,该读取返回 0 表示客户端已关闭,这可能会导致您出现问题?

于 2009-03-25T08:34:30.573 回答
3

客户端负责关闭连接。

客户端和服务器都必须关闭并关闭套接字。客户端没有完成关闭(不太可能 - 因为它会运行终结器)或服务器没有关闭套接字(可能)。

using (Socket s = new Socket(/* */)) {
  /* Do stuff */
  s.Shutdown(SocketShutdown.Both);
  s.Close();
}
于 2009-03-24T23:27:49.967 回答
0

您不应该只将关闭 TCP 套接字的责任留给客户端。如果客户端进程/机器崩溃了怎么办?

理想情况下,您应该设置一个超时,以便如果在一定时间后连接的套接字上没有收到流量,那么它会被服务器关闭。

于 2009-03-24T23:46:28.563 回答
0

无论客户端对套接字的所有操作都完成后发生什么,并且不再需要对套接字进行任何读取操作,客户端都应该发出关闭命令。

发出关闭命令只是告诉侦听器(服务器)需要关闭连接。

简单来说,当服务器再次发出读取命令(listener.read() 或 listener.beginread(...) 在异步模式下),读取将返回一个 0 字节的读取,这本身就表明套接字需要由侦听器关闭,因为客户端上的任何其他操作已停止。

于 2012-04-19T05:34:10.957 回答
-2

CLOSE_WAIT 的目的是在套接字关闭后等待一段时间,以防止重复使用相同的套接字号并从旧连接接收数据包。如果您真的很快打开和关闭大量的套接字,这只会让您感到悲伤。

编辑 - 它应该是 TIME_WAIT,而不是上面的 CLOSE_WAIT。

于 2009-03-24T23:29:18.760 回答