TechTalkz.com Logo

Go Back   TechTalkz.com Technology & Computer Troubleshooting Forums > Tech Support Archives > Programing Languages > C#(C Sharp)

Notices

Socket connect/disconnect, ReuseAddress, and TIME_WAIT

C#(C Sharp)


Reply
 
Thread Tools Display Modes
Old 13-11-2007, 09:34 PM   #1
Rob Gravereaux
Guest
 
Posts: n/a
Socket connect/disconnect, ReuseAddress, and TIME_WAIT

Visual Studio 2005, .Net 2.0, Vista, XP.

I have a client Tcp socket that is bound to a particular port and connecting
to a remote host. In order to allow reconnects I'm setting the ReuseAddress
socket option. This is somewhat dubious I know, but...

With the ReuseAddress option, a bind to a local port in a TIME_WAIT state
(netstat -a) does succeed, but the socket connect is failing with the 'Only
one usage of each socket address...' message. For example, in the following
code, call Connect(), then Disconnect(), then Connect() again (within the
TIME_WAIT period, about 4 minutes) and s.Connect(...) throws an exception.

There are a few posts I've seen that specify using the ReuseAddress socket
option in this scenario. Am I missing something? How can I successfully bind
to a local port that is already in a TIME_WAIT state and successfully
connect?

Some sample code...

private bool m_bConnected;

private Socket m_Socket;

private void Connect()
{
string sLocalHost = txtInboundLocalHost.Text;
int iLocalPort = int.Parse(txtInboundLocalPort.Text);
string sRemoteHost = txtInboundRemoteHost.Text;
int iRemotePort = int.Parse(txtInboundRemotePort.Text);

// Create socket and set options.
Socket s = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
s.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress, (int)1);

// Create local endpoint if desired.
if(!string.IsNullOrEmpty(sLocalHost))
{
// Use specified interface and port on local machine.
IPAddress ip;
if (IPAddress.TryParse(sLocalHost, out ip)
&& (ip.AddressFamily ==
System.Net.Sockets.AddressFamily.InterNetwork))
{
s.Bind(new IPEndPoint(ip, iLocalPort));
}
else
throw new ApplicationException("Not a valid IP
Address.");
}
else if(iLocalPort > 0)
{
// Use specified port on local machine, all interfaces.
s.Bind(new IPEndPoint(IPAddress.Any, iLocalPort));
}
// Otherwise, use default host & port...

// Connect to remote. This errors if port is in TIME_WAIT state.
s.Connect(sRemoteHost, iRemotePort);

m_Socket = s;
m_bConnected = true;
}

private void Disconnect()
{
if (m_bConnected)
{
// Shutdown socket and allow reuse.
m_Socket.Shutdown(SocketShutdown.Both);
m_Socket.Disconnect(true);
}
m_bConnected = false;
}

TIA.

Rob Gravereaux

  Reply With Quote
Old 13-11-2007, 10:36 PM   #2
Olie
Guest
 
Posts: n/a
Re: Socket connect/disconnect, ReuseAddress, and TIME_WAIT

I think ReuseAddress only applies to a UDP sockets and is not
applicable for TCP. The normal way to use TCP is to have a listener
socket from which you spawn the communications sockets on another
port.




  Reply With Quote
Old 14-11-2007, 12:32 AM   #3
Peter Duniho
Guest
 
Posts: n/a
Re: Socket connect/disconnect, ReuseAddress, and TIME_WAIT

On 2007-11-13 07:29:30 -0800, "Rob Gravereaux"
<rob_gravereaux@grsinc.com> said:

> Visual Studio 2005, .Net 2.0, Vista, XP.
>
> I have a client Tcp socket that is bound to a particular port and
> connecting to a remote host. In order to allow reconnects I'm setting
> the ReuseAddress socket option. This is somewhat dubious I know, but...
>
> With the ReuseAddress option, a bind to a local port in a TIME_WAIT
> state (netstat -a) does succeed, but the socket connect is failing with
> the 'Only one usage of each socket address...' message. For example, in
> the following code, call Connect(), then Disconnect(), then Connect()
> again (within the TIME_WAIT period, about 4 minutes) and s.Connect(...)
> throws an exception.
>
> There are a few posts I've seen that specify using the ReuseAddress
> socket option in this scenario. Am I missing something? How can I
> successfully bind to a local port that is already in a TIME_WAIT state
> and successfully connect?


Contrary to the other reply, ReuseAddress is valid on TCP sockets.

That said, it's not a panacea. Even using ReuseAddress, you won't be
able to accept a connection from the same client that was connected
when the previous connection was reset. You'll still need to be able
to tolerate a delay until the original TIME_WAIT socket has been
cleaned up.

The better solution is simply to make sure that your connections go
through a graceful shutdown before closing the socket, using the
Socket.Shutdown() method. Note that that means not only do you call
Shutdown(), but you don't close the socket until you've received
notification that the graceful shutdown has completed (for example,
receiving 0 bytes). I.e. don't just call Shutdown() followed
immediately by a call to Disconnect().

For what it's worth, there are a couple of Winsock newsgroups that,
while not .NET-specific, are sometimes read by people who know a lot
more about Winsock and networking in general than you'll find here
(like me ).

Pete

  Reply With Quote
Old 14-11-2007, 12:32 AM   #4
Peter Duniho
Guest
 
Posts: n/a
Re: Socket connect/disconnect, ReuseAddress, and TIME_WAIT

On 2007-11-13 10:39:10 -0800, Peter Duniho <NpOeStPeAdM@NnOwSlPiAnMk.com> said:

> [...]
> For what it's worth, there are a couple of Winsock newsgroups that,
> while not .NET-specific, are sometimes read by people who know a lot
> more about Winsock and networking in general than you'll find here
> (like me ).


I meant to provide the names of those newsgroups. Sorry.

alt.winsock.programming
comp.os.ms-windows.programmer.tools.winsock

The former is much more active than the latter, but you can find
quality help in either, especially if you're patient.

Pete

  Reply With Quote
Old 14-11-2007, 01:32 AM   #5
Rob Gravereaux
Guest
 
Posts: n/a
Re: Socket connect/disconnect, ReuseAddress, and TIME_WAIT

I'll try those other newsgroups. Thanks.

Can you point me to a discussion of 'graceful shutdown'. AFAIK, Shutdown and
Close (Disconnect) is the way to close a socket. From the Socket class
documentation:

When you are finished sending and receiving data, use the Shutdown method to
disable the Socket. After calling Shutdown, call the Close method to release
all resources associated with the Socket.

I was looking at the connect/disconnect packets with WireShark and saw that
the sample code I was using was producing the proper(?) FIN, ACK exchange to
close the socket. IE, on the other hand, seems to send RST, ACK when closing
its sockets.

"Peter Duniho" <NpOeStPeAdM@NnOwSlPiAnMk.com> wrote in message
news:2007111310391016807-NpOeStPeAdM@NnOwSlPiAnMkcom...
> On 2007-11-13 07:29:30 -0800, "Rob Gravereaux" <rob_gravereaux@grsinc.com>
> said:
>
>> Visual Studio 2005, .Net 2.0, Vista, XP.
>>
>> I have a client Tcp socket that is bound to a particular port and
>> connecting to a remote host. In order to allow reconnects I'm setting the
>> ReuseAddress socket option. This is somewhat dubious I know, but...
>>
>> With the ReuseAddress option, a bind to a local port in a TIME_WAIT state
>> (netstat -a) does succeed, but the socket connect is failing with the
>> 'Only one usage of each socket address...' message. For example, in the
>> following code, call Connect(), then Disconnect(), then Connect() again
>> (within the TIME_WAIT period, about 4 minutes) and s.Connect(...) throws
>> an exception.
>>
>> There are a few posts I've seen that specify using the ReuseAddress
>> socket option in this scenario. Am I missing something? How can I
>> successfully bind to a local port that is already in a TIME_WAIT state
>> and successfully connect?

>
> Contrary to the other reply, ReuseAddress is valid on TCP sockets.
>
> That said, it's not a panacea. Even using ReuseAddress, you won't be able
> to accept a connection from the same client that was connected when the
> previous connection was reset. You'll still need to be able to tolerate a
> delay until the original TIME_WAIT socket has been cleaned up.
>
> The better solution is simply to make sure that your connections go
> through a graceful shutdown before closing the socket, using the
> Socket.Shutdown() method. Note that that means not only do you call
> Shutdown(), but you don't close the socket until you've received
> notification that the graceful shutdown has completed (for example,
> receiving 0 bytes). I.e. don't just call Shutdown() followed immediately
> by a call to Disconnect().
>
> For what it's worth, there are a couple of Winsock newsgroups that, while
> not .NET-specific, are sometimes read by people who know a lot more about
> Winsock and networking in general than you'll find here (like me ).
>
> Pete
>


  Reply With Quote
Old 14-11-2007, 02:33 AM   #6
Peter Duniho
Guest
 
Posts: n/a
Re: Socket connect/disconnect, ReuseAddress, and TIME_WAIT

On 2007-11-13 11:25:02 -0800, "Rob Gravereaux"
<> said:

> I'll try those other newsgroups. Thanks.
>
> Can you point me to a discussion of 'graceful shutdown'. AFAIK,
> Shutdown and Close (Disconnect) is the way to close a socket. From the
> Socket class documentation:
>
> When you are finished sending and receiving data, use the Shutdown
> method to disable the Socket. After calling Shutdown, call the Close
> method to release all resources associated with the Socket.


Unfortunately, the MSDN documentation does a better job describing how
to use .NET features that are unique to .NET. I've noticed that where
..NET wraps some other functionality, the docs tend to assume you're
already familiar with that functionality.

For this particular issue, I recommend the usual Winsock resources,
which would include MSDN's docs for Winsock itself, as well as the
Winsock FAQ. You can start here:


Check out also:



> I was looking at the connect/disconnect packets with WireShark and saw
> that the sample code I was using was producing the proper(?) FIN, ACK
> exchange to close the socket. IE, on the other hand, seems to send RST,
> ACK when closing its sockets.


That could be simply due to the nature of the HTTP connections. IE is
likely to not be the one to initiate a connection closure, since at
least with the simplest HTTP usage, the client just receives data until
the server closes the connection. So the server would call shutdown(),
but the client would just close the socket when it receives 0 bytes.

I admit, I don't know a whole lot about HTTP, and I don't know how the
feature of reusing HTTP connections affects this behavior (e.g. is the
server still responsible for closing the connection?). But the basic
issue remains: you should call Shutdown() and then not close the socket
until you have received notification that you've gotten all the data
from the socket (i.e. received 0 bytes).

Pete

  Reply With Quote
Old 14-11-2007, 09:13 PM   #7
Rob Gravereaux
Guest
 
Posts: n/a
Re: Socket connect/disconnect, ReuseAddress, and TIME_WAIT

My mention of IE is only in terms of it being a TCP client. AFAIK, the
original HTTP protocol stated the server closes the socket after sending the
response. More current versions of HTTP allow the socket to stay open and
the client can make further http requests. Wireshark shows IE on my machine
keeping sockets open until IE shuts down. At that point IE closes all open
sockets via RST, ACK which is a hard shutdown. In this case the socket on
the client PC does not enter a TIME_WAIT state, and can immediately be used
again in a Socket.Bind() and Socket.Connect().

The ftp command line utility also seems to exhibit this behaviour. When
quitting it closes the socket with RST, ACK. The socket on the client PC
does not enter a TIME_WAIT state.

I did some further work with the .Net socket code shown earlier in this
thread. Your comment earlier about reading from the socket while closing is
echoed in the MSDN docs for the Winsock 2 shutdown function
(, however the .Net
docs for Socket.Shutdown
()
state the proper way to close a socket is to call Socket.Shutdown() followed
by Socket.Close(). This results in the FIN,ACK exchange, and is a graceful
shutdown of the socket. The socket on the client PC then enters a TIME_WAIT
state and cannot be used in a Socket.Bind() and Socket.Connect() until the
TIME_WAIT period expires.

Replacing the Socket.Shutdown() and Socket.Close() with just Socket.Close()
results in an RST,ACK. This is a hard shutdown. The port on the client does
NOT enter a TIME_WAIT state and the port can immediately be used in a
Socket.Bind() and Socket.Connect(). Using Socket.Close(int) specifying a
timeout value results in a graceful shutdown. Using the previous code:

Graceful shutdown:
private void Disconnect()
{
if (m_bConnected)
{
// Graceful shutdown
m_Socket.Shutdown(SocketShutdown.Both);
m_Socket.Close(); // or possibly m_Socket.Disconnect(true);
}
m_bConnected = false;
}

Hard shutdown:
private void Disconnect()
{
if (m_bConnected)
{
// Hard shutdown.
m_Socket.Close();
}
m_bConnected = false;
}

So, using Socket.Close() seems to be a workaround for my issue, however I'd
still like to know how it is possible to bind and connect to a port in a
TIME_WAIT state. The .Net docs seem to suggest its possible with the
ReuseAddress socket option, and the Socket.Disconnect(true) method. Has
anyone gotten this to work successfully?

Thanks.


"Peter Duniho" <> wrote in message
news:2007111311594650073-NpOeStPeAdM@NnOwSlPiAnMkcom...
> On 2007-11-13 11:25:02 -0800, "Rob Gravereaux" <>
> said:
>
>> I'll try those other newsgroups. Thanks.
>>
>> Can you point me to a discussion of 'graceful shutdown'. AFAIK, Shutdown
>> and Close (Disconnect) is the way to close a socket. From the Socket
>> class documentation:
>>
>> When you are finished sending and receiving data, use the Shutdown method
>> to disable the Socket. After calling Shutdown, call the Close method to
>> release all resources associated with the Socket.

>
> Unfortunately, the MSDN documentation does a better job describing how to
> use .NET features that are unique to .NET. I've noticed that where .NET
> wraps some other functionality, the docs tend to assume you're already
> familiar with that functionality.
>
> For this particular issue, I recommend the usual Winsock resources, which
> would include MSDN's docs for Winsock itself, as well as the Winsock FAQ.
> You can start here:
>
>
> Check out also:
>
>
>
>> I was looking at the connect/disconnect packets with WireShark and saw
>> that the sample code I was using was producing the proper(?) FIN, ACK
>> exchange to close the socket. IE, on the other hand, seems to send RST,
>> ACK when closing its sockets.

>
> That could be simply due to the nature of the HTTP connections. IE is
> likely to not be the one to initiate a connection closure, since at least
> with the simplest HTTP usage, the client just receives data until the
> server closes the connection. So the server would call shutdown(), but
> the client would just close the socket when it receives 0 bytes.
>
> I admit, I don't know a whole lot about HTTP, and I don't know how the
> feature of reusing HTTP connections affects this behavior (e.g. is the
> server still responsible for closing the connection?). But the basic
> issue remains: you should call Shutdown() and then not close the socket
> until you have received notification that you've gotten all the data from
> the socket (i.e. received 0 bytes).
>
> Pete
>


  Reply With Quote
Old 17-11-2007, 07:31 PM   #8
Mike Blake-Knox
Guest
 
Posts: n/a
Re: Socket connect/disconnect, ReuseAddress, and TIME_WAIT

In article <>, Rob Gravereaux
wrote:
> I have a client Tcp socket that is bound to a particular port and connecting*
> to a remote host. In order to allow reconnects I'm setting the ReuseAddress*
> socket option. This is somewhat dubious I know, but...
>
> With the ReuseAddress option, a bind to a local port in a TIME_WAIT state*
> (netstat -a) does succeed, but the socket connect is failing with the 'Only*
> one usage of each socket address...' message. For example, in the following*
> code, call Connect(), then Disconnect(), then Connect() again (within the*
> TIME_WAIT period, about 4 minutes) and s.Connect(...) throws an exception.


Most TCP clients don't specify a local port and hence don't use the
ReuseAddress socket option. Normally, the client connects to the server with
its hostname and the well known port it's listening on while the client's
operating system (TCP stack) chooses the local port. The server does use the
ReuseAddress option so it can bind to the well-known port immediately after
it's restarted (e.g., after an exception of some kind).

Mike

  Reply With Quote
Old 09-02-2009, 08:40 AM   #9
Newbie
 
Join Date: Feb 2009
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
Rep Power: 0 ozisnowman is an unknown quantity at this point


OS: Windows XP


Re: Socket connect/disconnect, ReuseAddress, and TIME_WAIT

After an ungraceful disconnection which you can check for by attempting to read/peek, you should not be trying to reuse the address or perform another bind, listen on the same port because the resources are unavailable during the TIME_WAIT period.

Your server socket which you created and performed the bind and listen on should remain open and should not be closed. It should remain open to accept further client connection attempts.

When you have created a server socket ie using the socket class, ipendpoint, bind, listen etc... you then listening for client connections
it is here that you need to create a client instance from you server socket using the Socket.Accept() ie.
Socket clientSocket = serverSocket.Accept();

It is then the clientSocket instance that you use to read if any data is available or if the connection has closed ungracefully... when the server has finished with the client or when the client has closed disgracefully then close the client clientSocket.Close().

The serverSocket though is still bound and listening for new client connections.
ozisnowman is offline   Reply With Quote
Reply

Thread Tools
Display Modes



< Windows Help - MS Office Help - Hardware Support >


New To Site? Need Help?

All times are GMT +5.5. The time now is 01:51 AM.


vBulletin, Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO
Copyright © 2005-2009, TechTalkz.com. All Rights Reserved - Privacy Policy
Valid XHTML 1.0 Transitional