Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boost UDP socket issue on unix - bind: address already in use

First of all, I know there are several other threads on the same theme, but I was unable to find anything in those that could help me so I'll try to be very specific with my situation.

I have set up a simple UDP Client / UDP Server pair that is responsible to send data between several parallel simulations. That is, every instance of the simulator is running in a separate thread and send data on a UDP socket. In the master thread the server is running and routes the messages between the simulations.

The (for this problem) important parts of the server code looks like this:

UDPServer::UDPServer(boost::asio::io_service &m_io_service) :
   m_socket(m_io_service, udp::endpoint(udp::v4(), PORT_NUMBER)),
   m_endpoint(boost::asio::ip::address::from_string("127.0.0.1"), PORT_NUMBER)
{
   this->start_receive();
};

void UDPServer::start_receive() {

   // Set SO_REUSABLE to true
   boost::asio::socket_base::reuse_address option(true);
   this->m_socket.set_option(option);

   // Specify what happens when a message is received (it should call the handle_receive function)
   this->m_socket.async_receive_from(   boost::asio::buffer(this->recv_buffer),
                                        this->m_endpoint,
                                        boost::bind(&UDPServer::handle_receive, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));

};

This works fine on my windows workstation.

The thing is; I want to be able to run this on a linux cluster, which is why I compiled it and tried to run it on a cluster node. The code compiled without a hitch, but when I try to run it I get the error

bind: address already in use

I use a port number above 1024, and have verified that it is not in use by another program. And as is seen above, I also set the reuse_address option, so I really don't know what else could be wrong.

like image 871
Fabian Jonsson Avatar asked Sep 09 '14 14:09

Fabian Jonsson


People also ask

How do I fix Bind Address Already in use?

The Error “address already in use” occurred because some process was already running on the same port. So we can resolve the issue just by killing the process. To stop the process, we need the process ID (PID), which we can fetch using the lsof command.


1 Answers

To portably use SO_REUSEADDR you need to set the option before binding the socket to the wildcard address:

UDPServer::UDPServer(boost::asio::io_service &m_io_service) :
   m_socket(m_io_service, udp::v4()),
   m_endpoint()
{
   boost::asio::socket_base::reuse_address option(true);
   this->m_socket.set_option(option);
   this->m_socket.bind(udp::endpoint(udp::v4(), PORT_NUMBER));
   this->start_receive();
}

In your original code, the constructor that takes an endpoint constructs, opens and binds the socket in a single line - it's concise but not very flexible. Here we're constructing and opening the socket in the constructor call, and then binding it later after we set the option.

As an aside, there's not much point initialising m_endpoint if you're just going to use it as the out argument of async_receive_from anyway.

like image 72
ecatmur Avatar answered Oct 11 '22 20:10

ecatmur