4

I have a TCP Tunnel in C#. I need to open and close the tunnel which is my app between a server and a client. I'm using this to close the data connection to test out another app. I have to use particular ports.

On the second, third, nth connection depending on how long I wait to reconnect, I receive a 10048 error code - "Address already in use" when binding my socket. When closing the sockets, I do perform ShutDown.Both and Close in hopes of clearing out the ports, but when I do a netstat in a command prompt I still find the ports held in TIME_WAIT. I've also set the sockets to no linger. Lastly I tried to make a loop to check the status of the port, but it ends in a somewhat endless loop. I'm thinking it's that 4 minute TIME_WAIT rule.

I have a function to display a nestat query and I find that when I run that and check until the port goes from ESTABLISHED and into TIME_WAIT that I can bind, but when I use the same data from this query to bind on a loop when the status reaches TIME_WAIT, I get a 10048. Is there a brief moment in time allowed by my button click that allows me to bind? Is there a state between TIME_WAIT and ESTABLISHED I'm hitting in the loop and not when I do it with button clicks? I read TIME_WAIT should stop me from binding altogether, but this does not appear to be true. Can anybody explain this?

I apologize to you code lovers. Not thinking this will change anything though. I just need a better understanding of port states.

    public bool CheckAvailablePorts()
    {
        int temp=0;
        bool availPort= true;
        m_config = new AppConfig();
        if (!m_config.initialize())
        {
            System.Diagnostics.Debug.WriteLine("Error loading configuration file.  Exiting...");
            return false;
        }
        else
        {

//checking through all the ports that have been set to connect on

            foreach (ProxyConfig cfg in m_config.m_proxyConfigs)
            {
                availPort = true;
                temp = cfg.localEP.Port;
                DataView dv = FindEstablishedSockets();//returns netstat query
                foreach (DataRowView rowView in dv)
                {
                    DataRow row = rowView.Row;

                    if ((Convert.ToInt32(row["Local Port"].ToString()) == temp) && (row["Status"].ToString().Equals("Established")))
                    {
                        System.Diagnostics.Debug.WriteLine("Port: " + temp + " is still locked");
                        availPort = false;
                        break;
                    }
                }
            }
            return availPort;
        }
    }

//snippet out of a bigger function which checks for availability and then sleeps if false and runs again

            bool temp = false;
            while (!temp)
            {
                temp = monitor.CheckAvailablePorts();
                System.Threading.Thread.Sleep(2000);
            }
            System.Threading.Thread.Sleep(3000);
            monitor.startApplication(); //starts all the binding
  • On windows, when you release the port, it stays in the TIME_WAIT for some configurable timeout. There's a registry setting for this, `HKLM/System/CurrentControlSet/Services/Tcpip/Parameters/TCPTimedWaitDelay` – Chris O Apr 08 '11 at 13:32
  • Depending on who closes the Connection, Time_wait may happen on the server or the client side, maybe let the client care about this? – Stephan B Apr 08 '11 at 13:37
  • http://www.isi.edu/touch/pubs/infocomm99/infocomm99-web/ suggested some changes to TCP to solve this. I don't think his ideas made it, but there are some details on the problem. – Stephan B Apr 08 '11 at 13:44
  • You probably dont want to change the machine wide time wait setting, see here for my thoughts on TIME_WAIT: http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html – Len Holgate Apr 09 '11 at 08:27

3 Answers3

0

You need to be a bit more specific as it's hard to know what you are doing. Shorter text and a code sample would help.

I need to open and close connections and then reopen them again

That should not be a problem if it's in the client. If it's server-side, please explain why.

The config file on the server is looking for a particular port, so when I reconnect I need the same port open again

What do you mean? If you mean the listening port: You should never close the listener socket. If you do not want to accept more than one socket, simply do not call Accept again until the client socket have been disconnected.

jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • Are you saying to kill the socket that accepts the EndAccept? – VengefulSakhmet Apr 08 '11 at 16:22
  • The same socket should call `BeginAccept` and `EndAccept` => the listener socket. That socket should live during the applications life time. The socket returned by `EndAccept`, the client socket, should be closed when the connection is closed. – jgauffin Apr 08 '11 at 18:38
  • It's unusual but there are legitimate reasons you might want to close the listening socket and there is nothing in the RFC's that refutes that. However it is tricky to do without going into a wait state. – Tony Edgecombe Sep 14 '21 at 12:40
0

I read TIME_WAIT should stop me from binding altogether, but this does not appear to be true.

There is an option you can use that will allow you to bind a local port that is in TIME_WAIT. This is very useful to ensure you don't have to wait 4 minutes after killing a server before restarting it.

int flag = 1;
sockfd = socket(...);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
bind(...);
Brian White
  • 8,332
  • 2
  • 43
  • 67
-2

Before closing a socket, you must read all the data sent by its peer, otherwise it will stay in TIME_WAIT to ensure a new socket will not read data intended for the previous (closed one). You could also try the no lingering option of the socket.

Details: http://msdn.microsoft.com/en-us/library/windows/desktop/ms738547%28v=vs.85%29.aspx

mBardos
  • 2,872
  • 1
  • 19
  • 16
  • That's actually not true; well, it's muddled. See http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html for details. – Len Holgate Feb 02 '12 at 09:05
  • This is *entirely* untrue. Pending data has nothing to do with TIME_WAIT whatsoever. It is all discarded when you close the socket, and any further data that arrives causes a reset to be issued. – user207421 Aug 20 '15 at 00:29
  • wow, that was a really old post of mine... resurrected ;) I stand corrected! – mBardos Sep 08 '15 at 18:14