8

I am using .Net's socket class and I am using the following code:

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

This then blocks for exactly two minutes. I have specified true because I am going to reuse the socket immediately and re-establish the connection. Whether I have the Shutdown call in there or not it blocks for two minutes. The only thing I can do is pass false to disconnect. But I want to reuse the socket.

Any ideas?

UPDATE:

I have read the codes. I have set the DontLinger option. It does not help.

UPDATE 2:

I have added a network trace as per request:

Trace 1: Using the DontLinger option

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

Trace 2: Using the Shutdown(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() 
uriDium
  • 13,110
  • 20
  • 78
  • 138
  • Can we see some of the surrounding code? it might be that there is something else causing the delay such as a loop or blocking call. – Tony Abrams Dec 07 '10 at 19:29

5 Answers5

4

Timeout in case of Shutdown followed by Disconnect or BeginDisconnect will occur in the case if the other side Socket is not Receiving.

Here how it works: Shutdown(SocketShutdown.Send) (or Both) produce SENDING of zero byte to other side. And then if you call Disconnect it will block until other side accept this zero byte packet. This is why socket always receive zero byte during in Accept during graceful disconnection from Socket. Linger option and other settings have no effect on this 2 minute delay. You may check connection state with TCPView. So proper way is to make sure other side is either in Receive mode OR physically disconnected OR actually destroyed socket - for example application quit (you will get immediate exception in this case without 2 minute delay).

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

Konstantin Salavatov
  • 4,370
  • 2
  • 25
  • 24
1

That may be to the Linger option. See here for more information: Graceful Shutdown, Linger Options, and Socket Closure

in .NET, you can change it with the Socket.SetSocketOption method.

EDIT: if it's not the Linger option, you should try to enable full socket traces, here is a .config sample:

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

EDIT: or you can hit what's called the TIME_WAIT, described here: Please explain the TIME_WAIT state which is 120ms. It's generally better to use Close() with the SocketOptionName.ReuseAddress rather than to use Disconnect(true). See comments here as well (in the comments section).

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • I have already tried to set the DontLinger option. It does not work. Anyway I used Socket.ShutDown so it should not be necessary. – uriDium Dec 03 '10 at 13:59
  • I have tried with the dont linger on and off and get the same trace. I have updated my question with the trace. – uriDium Dec 03 '10 at 14:21
  • Added a second trace using the Shutdown both method. – uriDium Dec 03 '10 at 14:26
  • You should use SetSocketOption ReuseAddress + Close rather then Disconnect(true) (I have updated my answer) – Simon Mourier Dec 03 '10 at 14:35
  • @Simon: I saw that from the Win Sock 2 API. I thought it mentioned this registry key parameter TcpTimedWaitDelay. I went and set that and it made no difference. Let me try your other suggestion. Thanks :) – uriDium Dec 03 '10 at 14:44
1

This might be what you are looking for.

If you need to call Disconnect without first calling Shutdown, you can set the DontLinger Socket option to false and specify a nonzero time-out interval to ensure that data queued for outgoing transmission is sent. Disconnect then blocks until the data is sent or until the specified time-out expires. If you set DontLinger to false and specify a zero time-out interval, Close releases the connection and automatically discards outgoing queued data.

From the docs.

Tony Abrams
  • 4,505
  • 3
  • 25
  • 32
  • I have already read this. It does not work. Even though the part says WITHOUT. Well I did call shutdown so all of that is invalid. – uriDium Dec 03 '10 at 13:57
  • From what I know, if shutdown is used it causes "all data is sent and received before the socket is closed" [Docs]. This results in the 2 minute delay, because it is finishing the sending and receiving of data before closing. The delay could be longer or shorter depending on the data being sent/received. – Tony Abrams Dec 03 '10 at 14:05
  • So it just choses to delay for 2 minutes to ensure the data is sent/received. That sounds horrible. – uriDium Dec 03 '10 at 14:07
  • I have just tried it without the shut down and I have set the socket option DontLinger to true and it still blocks for 2 minutes. – uriDium Dec 03 '10 at 14:09
0

It takes 2 min because the server probably did'nt close the socket when it received 0 bytes from the shutdown call of the client.

So client call shutdown. The server receive 0 bytes. Client call Disconnect : disconnect will wait the close of the socket from the server side. If the server don't close the socket, the disconnect of the client will take 2 min (timeout). If the server close the socket, the disconnect will be almost immediate.

Zelda
  • 1
  • 1
-3

Turns out there is some registry entry which controls how long a disconnect takes. It has something to do with the WinSock2 api.

uriDium
  • 13,110
  • 20
  • 78
  • 138