问题
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
回答1:
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.
回答2:
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(...);
回答3:
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
来源:https://stackoverflow.com/questions/5595331/port-stuck-in-time-wait