![]() |
|
|||||||
| Notices |
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
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 |
|
|
|
#2 |
|
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. |
|
|
|
#3 |
|
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 |
|
|
|
#4 |
|
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 |
|
|
|
#5 |
|
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 > |
|
|
|
#6 |
|
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 |
|
|
|
#7 |
|
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 > |
|
|
|
#8 |
|
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 |
|
|
|
#9 |
|
Newbie
Join Date: Feb 2009
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
Rep Power: 0
![]() OS:
|
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. |
|
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|
< Windows Help - MS Office Help - Hardware Support >
| New To Site? | Need Help? |