在.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)
[...]
这是代码,异常触发错误。请注意,在我的场景中,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;
套接字通过Session检索并在以后使用,并销毁:
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();
我尝试了各种标记组合,例如Linger
,ReuseAddress
,ExclusiveAddressUse
以及Listen
积压的值,但没有任何变化。
重要提示:如果没有ReuseAddress
选项,则套接字位于TIME_WAIT
中,如netstat -ano
所示。当我使用ReuseAddress
时,套接字卡在CLOSE_WAIT
中。
我完全了解其含义:有没有办法以编程方式减少特定套接字的CLOSE_WAIT或TIME_WAIT间隔而无需触及注册表?
我想知道在试图处理插座时我是否忘记了某些事情......
答案 0 :(得分:0)
事实证明,利用Session对象并不理想。第一次使用后端口将保持打开状态,并且根据netstat
显示的PID,IIS工作者将拥有它。因此,似乎无法在其上调用Close()
。
解决方案是在s1
之后关闭服务器套接字(在我的示例中为Accept
):
[...]
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){
[...]
之前的解决方案使"清理"不必要的。