Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Address already in use with boost asio acceptor

I wrote a server that is listening for incomming TCP connections and clients connecting to it. When I shut down the server and restart it on the same port, I sometimes get the error message EADDRINUSE when calling bind(...) (error code: 98 on Linux). This happens even though I am setting the option to reuse the socket.

The error does not happen all the time, but it seems that it happens more often when clients are connected to the server and sending data while it shuts down. I guess the problem is that there are still pending connections while the server is shut down (related topic: https://stackoverflow.com/questions/41602/how-to-forcibly-close-a-socket-in-time-wait).

On the server side, I am using boost::asio::ip::tcp::acceptor. I initialize it with the option "reuse_address" (see http://beta.boost.org/doc/libs/1_38_0/doc/html/boost_asio/reference/basic_socket_acceptor.html). Here is the code snippet:

using boost::asio::ip::tcp;
acceptor acceptor::acceptor(io_service);
endpoint ep(ip::tcp::v4(), port);
acceptor.open(ep.protocol());
acceptor.set_option(acceptor::reuse_address(true));
acceptor.bind(ep);
acceptor.listen();

The acceptor is closed with:

acceptor.close();

I also tried using acceptor.cancel() before that, but it had the same effect. When this error occurred, I cannot restart the server on the same port for quite some time. Restarting the network helps, but is not a permanent solution.

What am I missing?

Any help would be greatly appreciated! :)

like image 256
Alexander Avatar asked Nov 16 '10 12:11

Alexander


2 Answers

These were originally a comment to the question.


does your server fork child processes? Also, are you sure the socket is in TIME_WAIT state? You might want to grab the netstat -ap output when this happens

like image 118
Sam Miller Avatar answered Oct 22 '22 17:10

Sam Miller


When you solve these problems "by force", it seems you are calling problems on your head, do not you?

There is a reason the default behavior requires you to wait, otherwise the network could for example confuse the ACK from the previous connection to be ACK for the new connection.

I would not allow this "solution" to be included in release builds in my team.

Remember, when the probability of error is very low, testing is extremely difficult!

like image 44
Hrissan Avatar answered Oct 22 '22 15:10

Hrissan