希望有人能帮助我们,因为我们正在深入的调查可以进行!
我们有一个用C#编写的简单异步套接字服务器,它接受来自ASP.NET web应用程序的连接,发送消息,执行一些处理(通常针对DB,但也针对其他系统),然后将响应发送回客户端。客户端负责关闭连接。
我们一直存在这样的问题:如果系统在很长一段时间(通常是几天)内负载很重,那么CLOSE_WAIT套接字就会在服务器框(netstat -a)上建立起来,以至于进程将不接受任何进一步的连接。在这一点上,我们必须反弹的过程,并关闭它再次运行。
我们尝试对我们的ASP.NET应用程序运行一些负载测试来尝试复制这个问题(因为从代码中推断出一些问题是不可能的)。我们认为我们已经成功地解决了这一问题,并在套接字服务器的日志中以SocketException的形式显示了问题的包跟踪:
System.Net.Sockets.SocketException: System.Net.Sockets.Socket.BeginSend上的远程主机强制关闭现有连接(Byte[]缓冲区、Int32偏移量、Int32大小、socketFlags SocketFlags、AsyncCallback回调、对象状态)
我尝试将数据包跟踪中的问题复制为一个单线程进程,直接与套接字服务器对话(使用ASP.NET应用程序所使用的相同代码),但无法实现。
有没有人对接下来的事情有什么建议可以尝试,检查,或者我们可能做错了什么?
发布于 2009-03-25 08:34:30
如果您的服务器正在积累CLOSE_WAIT
套接字,那么当连接完成时,它不会关闭它的套接字。如果您查看对Chris的帖子的注释中的状态图,您将看到,一旦套接字关闭并发送了CLOSE_WAIT
,FIN
就会转换为LAST_ACK
。
您说,由于异步的性质,确定在哪里执行这个任务很复杂?这应该不是问题,如果您的recv的回调返回0字节,您应该关闭套接字(假设您在客户端关闭连接时没有其他事情可做)。如果您确实需要担心是否继续发送,那么在这里执行一个关机(Recv),并记录一下您的客户端已经关闭了,一旦您发送完,执行一个关闭(发送)和一个关闭。
您可能是在read的回调中发出一个新的read,该回调返回0,指示客户端已经关闭,这可能会导致问题吗?
发布于 2009-03-24 23:27:49
客户端负责关闭连接。
客户端和服务器都必须关闭和关闭套接字。或者客户端没有完成关闭(不太可能--因为它会运行终结器),或者服务器不会关闭套接字(可能)。
using (Socket s = new Socket(/* */)) {
/* Do stuff */
s.Shutdown(SocketShutdown.Both);
s.Close();
}
发布于 2009-03-24 23:46:28
您不应该只将关闭TCP套接字的责任留给客户端。如果客户端进程/机器崩溃,会发生什么?
理想情况下,您应该设置一个超时,以便如果在连接的套接字上经过一定时间之后没有接收到任何通信量,那么服务器就会关闭它。
https://stackoverflow.com/questions/679643
复制相似问题