address already in use error on linux.

Started by
8 comments, last by hplus0603 15 years, 11 months ago
Hi! I'm writing a simple server and while testing it i need to start and stop it quite frequently. I noticed that sometimes it starts ok right after stop but sometimes it cannot bind for up to half a minute and gets EADDRINUSE error. What does it mean - does linux prevent the server from binding too often or what? My binding code is very simple and relyable so the fault is in sockets but how to handle it? Should i just wait until bind succeeds? If anyone faced such problem please give an idea. Many thanks in advance. Jay
ubuntu jaunty amd64
Advertisement
When you close a TCP socket, the OS puts it into a CLOSE_WAIT state (I think that's the state name, someone feel free to verify). When it's in this state, the socket is "reserved". This is so that if there are any stray packets on the network, when they arrive, the OS can discard them. If another app had quickly bound to the same address, then the packets would get processed for it, and that could cause problems (Although I'm not sure what, and you wouldn't see them in the application, it'd only be network-level stuff. Presumably you could get the socket disconnected if a disconnect packet was recieved or something).

You can tell the OS that you don't care by using setting SO_REUSEADDR to 1 with setsockopt().
The first possibility is that your server isn't actually stopped but still waiting, e.g. for an exstinging connection to be closed. Whether or not this is the case depends on how you stop your server. You may look with the ps command after a stop whether a process is still alive, and may kill it then hardly with a kill -KILL command.

The 2nd thing is that there is a mechanism that allows ports to be returned not immediately to the pool but keep it for some time virtually engaged. The mechanism may be turned on and off. Unfortunately, I currently don't remember how that mechanism is named... EDIT Evil Steve has named it, and that even before my post was finished :)
Thank you guys! The problem's gone. I added some code that calls setsockopt right after creation of a socket and now it seems to work fine. I found an interesting note for option SO_LINGER - the man page says
Quote:If SO_LINGER is not specified, and close() is issued, the system handles the call in a way that allows the process to continue as quickly as possible.
After more careful tests i found that the problem occurs only after transmitting some data client and reading client's response. So i guess there's some data pending when system issues an error.
After that i've got another question - is there any way to find what problem occurred at a level lower than socket level e.g. at TCP level?
ubuntu jaunty amd64
Quote:Original post by Jay I
Thank you guys! The problem's gone. I added some code that calls setsockopt right after creation of a socket and now it seems to work fine. I found an interesting note for option SO_LINGER - the man page says
Quote:If SO_LINGER is not specified, and close() is issued, the system handles the call in a way that allows the process to continue as quickly as possible.
After more careful tests i found that the problem occurs only after transmitting some data client and reading client's response. So i guess there's some data pending when system issues an error.
That makes sense. The socket probably doesn't need to go into a CLOSE_WAIT state if it's not sent or recv'd any data, since there shouldn't be any out there for it to deal with.

Quote:Original post by Jay I
After that i've got another question - is there any way to find what problem occurred at a level lower than socket level e.g. at TCP level?
What information would you want? You can use errno to get a more useful error code about what went wrong (Or WSAGetLastError() on Windows).
EDIT: Ah, that'd be how you got EADDRINUSE in the first place... What information do you want? There's nothing more low level than that.
Quote:Original post by Evil Steve
What information do you want? There's nothing more low level than that.

I mean some protocol specific information. When something goes wrong at socket level i can't tell user more than a man page on a socket level function contains, but if i have more information about a crash i'll be able
at least to gather it, analyze and finally provide user with more meaningful messages or even find a workaround that wouldn't involve user in fixing a problem. I just thought that if system provides a way to set protocol level options maybe it also provides a way to deal with protocol level errors.

ubuntu jaunty amd64
Quote:Original post by Jay I
Quote:Original post by Evil Steve
What information do you want? There's nothing more low level than that.

I mean some protocol specific information. When something goes wrong at socket level i can't tell user more than a man page on a socket level function contains, but if i have more information about a crash i'll be able
at least to gather it, analyze and finally provide user with more meaningful messages or even find a workaround that wouldn't involve user in fixing a problem. I just thought that if system provides a way to set protocol level options maybe it also provides a way to deal with protocol level errors.
The Winsock error codes on MSDN are just as relevant as the UNIX socket versions of the same error. There's really nothing lower level than you're being told already. The error codes aren't protocol or layer specific, they're giving you all the information the OS has available.
The point of CLOSE_WAIT is to resend lost ACKs for closing the channel. Immediately closing and reusing the channel will work fine on the server end, but will occasionally be very irritating on the client side.
Quote:Original post by Evil Steve
There's really nothing lower level than you're being told already.

Ok. At least i don't need to write more code:) Thanks.

ubuntu jaunty amd64
Quote:The point of CLOSE_WAIT is to resend lost ACKs for closing the channel.


The point is also to wait for any delayed packets that may be on the network, not yet delivered. If you immediately re-open the socket, especially with UDP, arrival of such packets may confuse your code.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement