2010-12-03 61 views
7

我使用的.Net的Socket类,我用下面的代码:为什么.Net Socket.Disconnect需要两分钟?

socket.Shutdown(SocketShutdown.Both); 
socket.Disconnect(true); 

这就块整整两分钟。我指定了true,因为我将立即重用套接字并重新建立连接。无论是否有关机呼叫,它都会阻塞两分钟。我能做的唯一事情就是传递错误来断开连接。但我想重用套接字。

任何想法?

UPDATE:

我已阅读代码。我已经设置了DontLinger选项。它没有帮助。

更新2:

我已经加入网络跟踪按请求:

跟踪1:使用DontLinger选项

System.Net.Sockets Verbose: 0 : [4668] Socket#5009246::Socket(InterNetwork#2) 
System.Net.Sockets Verbose: 0 : [4668] Exiting Socket#5009246::Socket() 
System.Net.Sockets Verbose: 0 : [4668] Socket#5009246::Connect(eee:nnnn#-2063562120) 
System.Net.Sockets Information: 0 : [4668] Socket#5009246 - Created connection from aaa.bbb.ccc.ddd.eee:nnnnn to www.xxx.yyy.zzz.:mmmm. 
System.Net.Sockets Verbose: 0 : [4668] Exiting Socket#5009246::Connect() 
System.Net.Sockets Verbose: 0 : [4668] Socket#5009246::Disconnect() 
System.Net.Sockets Verbose: 0 : [4668] Exiting Socket#5009246::Disconnect() 

迹线2:使用关机(SocketShutdown。都);

System.Net.Sockets Verbose: 0 : [0300] Socket#5009246::Socket(InterNetwork#2) 
System.Net.Sockets Verbose: 0 : [0300] Exiting Socket#5009246::Socket() 
System.Net.Sockets Verbose: 0 : [0300] Socket#5009246::Connect(ddd:eeeee#-2063562120) 
System.Net.Sockets Information: 0 : [0300] Socket#5009246 - Created connection from aaa.bbb.ccc.ddd:eeee to www.xxx.yyyy.zzzz:nnnnn. 
System.Net.Sockets Verbose: 0 : [0300] Exiting Socket#5009246::Connect() 
System.Net.Sockets Verbose: 0 : [0300] Socket#5009246::Shutdown(Both#2) 
System.Net.Sockets Verbose: 0 : [0300] Exiting Socket#5009246::Shutdown() 
System.Net.Sockets Verbose: 0 : [0300] Socket#5009246::Disconnect() 
System.Net.Sockets Verbose: 0 : [0300] Exiting Socket#5009246::Disconnect() 
+0

我们可以看到一些周围的代码吗?有可能是由于其他原因导致延迟,例如循环或阻塞呼叫。 – 2010-12-07 19:29:15

回答

-2

原来有一些注册表项控制断开连接需要多长时间。它与WinSock2 api有关。

0

这可能是灵儿选项。在这里看到更多的信息:Graceful Shutdown, Linger Options, and Socket Closure

在.NET中,你可以改变它与Socket.SetSocketOption方法。

编辑:如果不是灵儿选项,你应该尽量使全窝痕迹,这里是一个的.config样本:

<configuration> 
    <system.diagnostics> 
    <trace autoflush="true" /> 
    <sources> 
     <source name="System.Net.Sockets"> 
     <listeners> 
      <add name="SocketsTrace"/> 
     </listeners> 
     </source> 
    </sources> 

    <sharedListeners> 
     <add name="SocketsTrace" type="System.Diagnostics.TextWriterTraceListener" initializeData="SocketsTrace.log" /> 
    </sharedListeners> 

    <switches> 
     <add name="System.Net.Sockets" value="Verbose" /> 
    </switches> 
</configuration> 

编辑:或者你可以打什么所谓的TIME_WAIT ,在这里描述:Please explain the TIME_WAIT state这是120ms。使用Close()和SocketOptionName.ReuseAddress通常更好,而不是使用Disconnect(true)。请参阅注释here(在评论部分中)。

+0

我已经尝试设置DontLinger选项。这是行不通的。无论如何,我使用Socket.ShutDown,所以它不应该是必要的。 – uriDium 2010-12-03 13:59:17

+0

想法:尝试启用跟踪(我已经更新了我的答案) – 2010-12-03 14:09:57

+0

我已经尝试过不要逗留和关闭,并获得相同的跟踪。我用跟踪更新了我的问题。 – uriDium 2010-12-03 14:21:34

1

这可能是你正在寻找的。

如果您需要致电断开连接而不首先调用shutdown,您可以设置DontLinger Socket选项设置为false,并指定一个非零的超时间隔,以确保数据排队传出传输发送。然后断开连接,直到发送数据或直到指定的超时到期。如果将DontLinger设置为false并指定零超时间隔,则Close会释放连接并自动丢弃传出的排队数据。

docs

3

如果关闭,则在断开连接或BeginDisconnect的情况下,如果另一端的套接字不是正在接收,将发生超时。

这里它是如何工作的: Shutdown(SocketShutdown.Send)(或两者)产生零字节的SENDING到另一端。 然后,如果您调用断开连接,它将阻塞,直到另一方接受此零字节数据包。 这就是为什么套接字在从套接字正常断开连接期间在接受期间始终接收零字节的原因。 灵隐选项和其他设置对这2分钟的延迟没有影响。您可以使用TCPView检查连接状态。 所以正确的方法是确保另一端处于接收模式或物理断开连接或实际销毁套接字 - 例如退出应用程序(在这种情况下,您将在没有2分钟延迟的情况下立即得到异常)。

http://vadmyst.blogspot.ru/2008/04/proper-way-to-close-tcp-socket.html

相关问题