为什么.Net Socket.Disconnect需要两分钟?

时间:2010-12-03 13:46:21

标签: .net sockets

我正在使用.Net的套接字类,我正在使用以下代码:

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

这会阻塞两分钟。我已经指定了true,因为我将立即重用套接字并重新建立连接。我是否在那里有关机呼叫,它会阻塞两分钟。我唯一能做的就是传递false来断开连接。但我想重用套接字。

有什么想法吗?

更新

我已阅读了这些代码。我已经设置了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.Both);

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() 

5 个答案:

答案 0 :(得分:3)

如果另一侧Socket未接收,则会出现Shutdown,然后是Disconnect或BeginDisconnect超时的情况。

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

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

答案 1 :(得分:1)

这可能就是你要找的东西。

  

如果您需要在不先调用Shutdown的情况下调用Disconnect,则可以将DontLinger套接字选项设置为false并指定非零超时间隔,以确保发送排队等待传出传输的数据。断开然后阻塞,直到发送数据或直到指定的超时到期。如果将DontLinger设置为false并指定零超时间隔,则Close会释放连接并自动丢弃传出的排队数据。

来自docs

答案 2 :(得分:0)

这可能是Linger选项。有关详细信息,请参阅此处:Graceful Shutdown, Linger Options, and Socket Closure

在.NET中,您可以使用Socket.SetSocketOption方法更改它。

编辑:如果它不是Linger选项,你应该尝试启用完整套接字跟踪,这是一个.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。通常使用SocketOptionName.ReuseAddress而不是使用Disconnect(true)来更好地使用Close()。另请参阅评论here(在评论部分)。

答案 3 :(得分:0)

需要2分钟,因为服务器从客户端的关闭调用接收到0个字节时可能没有关闭套接字。

因此客户端呼叫关闭。服务器收到0个字节。 客户端调用Disconnect:断开连接将等待服务器端套接字的关闭。 如果服务器没有关闭套接字,则断开客户端连接将花费2分钟(超时)。 如果服务器关闭套接字,断开连接将立即生效。

答案 4 :(得分:-2)

原来有一些注册表项可以控制断开连接的时间。它与WinSock2 api有关。