C# TCP套接字服务器构建关闭\u偶尔会随着时间的推移等待,直到无法操作为止

C# TCP套接字服务器构建关闭\u偶尔会随着时间的推移等待,直到无法操作为止,c#,performance,sockets,crash,wireshark,C#,Performance,Sockets,Crash,Wireshark,希望有人能帮助我们,因为我们正在进行尽可能深入的调查 我们有一个用C#编写的简单异步套接字服务器,它接受来自ASP.NET web应用程序的连接,发送消息,执行一些处理(通常针对DB,但也针对其他系统),然后将响应发送回客户端。客户端负责关闭连接 我们一直遇到这样的问题:如果系统长时间(通常是几天)处于重载状态,服务器盒(netstat-a)上的CLOSE_WAIT套接字就会累积到进程无法接受任何进一步连接的程度。在这一点上,我们必须反弹进程并再次运行它 我们已经尝试对ASP.NET应用程序运行

希望有人能帮助我们,因为我们正在进行尽可能深入的调查

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

我们一直遇到这样的问题:如果系统长时间(通常是几天)处于重载状态,服务器盒(netstat-a)上的CLOSE_WAIT套接字就会累积到进程无法接受任何进一步连接的程度。在这一点上,我们必须反弹进程并再次运行它

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

System.Net.Sockets.SocketException:远程主机强制关闭了现有连接 位于System.Net.Sockets.Socket.BeginSend(字节[]缓冲区、Int32偏移量、Int32大小、SocketFlags SocketFlags、AsyncCallback回调、对象状态)

我曾尝试将数据包跟踪中的问题复制为直接与套接字服务器对话的单线程进程(使用与ASP.NET应用程序相同的代码),但无法实现

有没有人对下一步的尝试、检查或明显的错误有什么建议

客户端负责关闭连接

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


CLOSE_WAIT是指在套接字关闭后挂起一段时间,以防止重复使用相同的套接字编号和从旧连接接收数据包。这只会给你带来悲伤,如果你真的很快地打开和关闭了很多插座


编辑-上面应该是时间等待,而不是关闭等待。

您不应该将关闭TCP套接字的责任只留给客户端。如果客户端进程/计算机崩溃,会发生什么情况


理想情况下,您应该有一个超时,这样,如果在一段时间后连接的套接字上没有收到流量,则服务器将关闭该套接字。

如果您的服务器正在累积
CLOSE\u WAIT
sockets,则在连接完成时它不会关闭其套接字。如果您查看Chris帖子评论中的状态图,您将看到,一旦套接字关闭并且发送了
FIN
,则
CLOSE\u WAIT
将转换到
LAST\u ACK

你说由于异步的特性,决定在哪里做这件事很复杂?这应该不是问题,如果recv的回调返回0字节,则应该关闭套接字(假设在客户端关闭其连接端后,您没有其他事情要做)。如果您确实需要担心继续发送,请在此处执行关机(recv),并记下您的客户端已关闭,一旦发送完毕,请执行关机(send)并关闭

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

看看图表

http://en.wikipedia.org/wiki/File:Tcp_state_diagram_fixed.svg http://en.wikipedia.org/wiki/File:Tcp_state_diagram_fixed.svg 您的客户端通过调用close()关闭连接,close()将FIN发送到服务器套接字,服务器套接字确认FIN,其状态现在更改为close\u WAIT,并保持这种状态,除非服务器对该套接字发出close()调用


服务器程序需要检测客户端是否已中止连接,然后立即关闭()以释放端口。怎么用?请参阅read()。读取文件末尾(表示接收到FIN)时,返回零。

无论客户端完成套接字上的所有操作后发生什么情况,并且不需要再对套接字执行任何读取操作,客户端都应发出close命令

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


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

如果由于某种原因连接被楔入,它们可能会停留更长的时间,请参阅:。这不是时间等待之类的自然现象。我是不是越来越接近时间等待,时间等待变得混乱或是什么?你想到的是时间等待Chris。因为问题是关于时间等待的,他的答案是不相关的。在客户端,套接字作为使用的一部分被关闭(…)block-但我们现在不显式执行.Shutdown和.Close-这在正常测试中不是问题。服务器在我们能找到的所有代码路径中都显式地执行这两个操作(因为它是异步的,所以很复杂)。@Kieran-我认为,服务器进程的反弹清除了关闭等待,这表明您没有在某个地方关闭。 http://en.wikipedia.org/wiki/File:Tcp_state_diagram_fixed.svg