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

问题描述 投票:7回答:5

我正在使用.Net的socket类,我使用以下代码:

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() 
.net sockets
5个回答
4
投票

如果另一侧Socket未接收,则在发生关闭,然后是Disconnect或BeginDisconnect的情况下将发生超时。

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

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


1
投票

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

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

来自docs


0
投票

这可能是Linger选项。有关更多信息,请参见此处: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。通常使用SocketOptionName.ReuseAddress而不是使用Disconnect(true)来更好地使用Close()。请参阅评论here(在评论部分)。


0
投票

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

所以客户端调用shutdown。服务器接收0个字节。客户端调用Disconnect:disconnect将等待服务器端的套接字关闭。如果服务器没有关闭套接字,则客户端断开连接需要2分钟(超时)。如果服务器关闭套接字,则断开连接几乎是立即的。


-2
投票

事实证明,有一些注册表项可以控制断开连接的时间。它与WinSock2 api有关。

© www.soinside.com 2019 - 2024. All rights reserved.