unix上的UDP套接字问题 - bind:已经在使用的地址

时间:2014-09-09 14:30:50

标签: c++ linux sockets boost udp

首先,我知道在同一个主题上还有其他一些主题,但我无法找到任何可以帮助我的内容,所以我会尝试对我的情况非常具体。

我已经设置了一个简单的UDP客户端/ UDP服务器对,负责在几个并行模拟之间发送数据。也就是说,模拟器的每个实例都在一个单独的线程中运行,并在UDP套接字上发送数据。在主线程中,服务器正在运行,并在模拟之间路由消息。

(对于这个问题)服务器代码的重要部分如下所示:

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));

};

这在我的Windows工作站上运行良好。

事情是;我希望能够在Linux集群上运行它,这就是我编译它并尝试在集群节点上运行它的原因。代码编译顺利,但当我尝试运行它时,我得到错误

bind: address already in use

我使用1024以上的端口号,并确认其他程序未使用它。如上所示,我还设置了reuse_address选项,所以我真的不知道还有什么可能是错的。

2 个答案:

答案 0 :(得分:4)

portably use SO_REUSEADDR,您需要在将套接字绑定到通配符地址之前设置该选项:

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();
}

在原始代码中,采用endpoint构造的构造函数在一行中打开并绑定套接字 - 它简洁但不够灵活。这里我们在构造函数调用中构造并打开套接字,然后在设置选项后再绑定它。

顺便说一下,如果您只是将其用作m_endpoint的out参数,那么初始化async_receive_from并不多。

答案 1 :(得分:0)

尝试在Linux上运行以下命令,以查看该端口是否已被其他程序使用。

netstat -antup | grep 1024

如果你收到“已经在使用的地址”,那么它肯定会被其他一些程序使用。如果上面的命令产生一些结果,则终止命令中报告的进程ID。如果这不起作用,请尝试将端口号更改为其他任意端口,并检查问题是否仍然存在。