繁体   English   中英

以编程方式减少TIME_WAIT或CLOSE_WAIT

[英]Programmatically reducing TIME_WAIT or CLOSE_WAIT

.aspx页中,我需要将套接字绑定到端口,使用它,然后处置它。 它第一次起作用,但是第二次访问该页面时,出现以下异常:

[Exception in bind: System.Net.Sockets.SocketException (0x80004005): Only one usage of each socket 
 address (protocol/network address/port) is normally permitted
at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, 
 SocketAddress socketAddress)
at System.Net.Sockets.Socket.Bind(EndPoint localEP)
[...]

这是代码,其中Exception触发了错误。 请注意,在我的场景中,Accept()块是完全可以接受的。

IPAddress ipAddress = IPAddress.Parse(ip);
Socket s1 = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ep = new IPEndPoint(ipAddress, port);
try {
    s1.Bind(ep);
} catch(Exception ex) {
    HttpContext.Current.Response.Write("[Exception in bind: "+ ex + "\n");
    return;
}
s1.Listen(32);
// block until there's a connection
Socket s2 = s1.Accept();
// save for later
Session["s1"] = s1;
Session["s2"] = s2;

套接字是通过会话检索的,以后可以使用并销毁:

Socket s1 = Session["s1"] as Socket;
Socket s2 = Session["s2"] as Socket;

// ... use the socket ...

// cleanup
s2.Shutdown(SocketShutdown.Both);
s2.Disconnect(true);
s2.Close();
s2.Dispose();
s1.Shutdown(SocketShutdown.Both);
s1.Disconnect(true);
s1.Close();
s1.Dispose();

我尝试了标志的各种组合,例如LingerReuseAddressExclusiveAddressUseListen待办事项的值,但没有任何变化。

重要说明:如果没有ReuseAddress选项,则套接字位于TIME_WAIT ,如netstat -ano所示。 当我使用ReuseAddress ,套接字卡在CLOSE_WAIT

我完全了解其中的含义 :是否有一种方法可以以编程方式减少特定套接字的CLOSE_WAIT或TIME_WAIT间隔,而无需触摸注册表?

我想知道是否在尝试处置套接字时遗忘了一些东西...

事实证明,利用Session对象不是理想的选择。 首次使用后,该端口将保持打开状态,根据netstat显示的PID,IIS Worker将拥有该端口。 因此,似乎无法在其上调用Close()

解决方案是在Accept之后关闭服务器套接字(在我的示例中为s1 ):

[...]
s1.Listen(32);
// block until there's a connection
Socket s2 = s1.Accept();
// *close the server socket*
s1.Close();
// only save s2 for later
Session["s2"] = s2;

然后仅使用s2 ,例如:

// ...later on
Socket s1 = Session["s1"] as Socket;
try {
    while ((bytesRead = s1.Receive(receiveBuffer)) > 0 ) {
        byte[] received = new byte[bytesRead];
        Array.Copy(receiveBuffer, received , bytesRead);
        Response.BinaryWrite(received);
    }
} catch(Exception ex){
[...]

先前的解决方案使“清理”变得不必要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM