【问题标题】:Asio: 'Address Already In Use' on Bind, yet I can still ConnectAsio:Bind 上的“地址已在使用中”,但我仍然可以连接
【发布时间】:2016-02-12 15:06:09
【问题描述】:

我遇到的问题似乎没有问题,但我不明白错误所在。基本上,我一直在尝试编写“优雅地”关闭两端的 tcp 套接字的代码。在我的程序结束时,在关闭它们之前,我关闭了我的套接字。在快速重新启动时,这是我试图解决的问题,因为套接字在两侧徘徊而导致的更糟糕的崩溃问题不再发生。关闭/然后关闭似乎在这方面起作用。

但是,我仍然收到“地址已在使用中”,这通常导致我无法连接。现在我可以在那个错误之后连接就好了。我已经阅读了很多关于graceful shutdownreuse address 等主题的文章。而且我想我的问题是,如果绑定时出现套接字错误(“地址已在使用中”),在成功打开后,它是否可能能够连接到端点?换句话说,如果地址 实际上已经在使用中,如何建立连接?另外,值得注意的是,重用地址在这种情况下不起作用。因为我使用相同的套接字设置、本地/远程地址和 ip。

【问题讨论】:

  • 你确定旧进程真的被杀死了,所以你连接到旧进程而不是新进程会出现错误吗?
  • 如果这是在 linux/os x/freebsd 上,你可以试试 netstat -na|grep your-port-number 看看进程是否还在。
  • 感谢 cmets。 @Joachim,我很确定这个过程已经死了。我已经完全关闭了窗口,并且肯定会关闭并关闭和套接字析构函数。如果操作系统以某种方式允许新进程控制旧进程套接字,那将是非常惊人的。看起来很不安全。 kometen,我一定会试一试的

标签: sockets c++11 tcp boost-asio


【解决方案1】:

未能将套接字bind() 连接到某个地址不会使底层套接字无效。因此,connect() 操作将继续使用未绑定的套接字,让内核绑定到本地端点。


这是一个完整的例子demonstrating这个行为:

#include <boost/asio.hpp>
#include <boost/bind.hpp>

// This example is not interested in all handlers, so provide a noop function
// that will be passed to bind to meet the handler concept requirements.
void noop() {}

int main()
{
  using boost::asio::ip::tcp;

  // Create all I/O objects.
  boost::asio::io_service io_service;
  tcp::acceptor acceptor(io_service, {tcp::v4(), 0});
  tcp::socket server(io_service, tcp::v4());

  // Open socket1, binding to a random port.
  tcp::socket socket1(io_service, {boost::asio::ip::address_v4::any(), 0});
  tcp::socket socket2(io_service); // non-open

  // Explicitly open client2, which will bind it to the any address.
  boost::system::error_code error;  
  socket2.open(tcp::v4(), error);
  assert(!error);
  assert(socket2.local_endpoint().port() == 0);

  // Attempt to bind socket2 to socket1's address will fail with
  // an already in use error, leaving socket2 bound to the any endpoint.
  // (e.g. a failed bind does not have side effects on the socket) 
  socket2.bind(socket1.local_endpoint(), error);
  assert(error == boost::asio::error::address_in_use);
  assert(socket2.local_endpoint().port() == 0);

  // Connect will defer to the kernel to bind the socket.
  acceptor.async_accept(server, boost::bind(&noop));  
  socket2.async_connect(acceptor.local_endpoint(), 
    [&error](const boost::system::error_code& ec) { error = ec; });
  io_service.run();
  io_service.reset();
  assert(!error);
  assert(socket2.local_endpoint().port() != 0);
}

【讨论】:

  • 非常感谢您的解释。
猜你喜欢
  • 2020-10-22
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 2013-10-21
  • 2021-02-02
  • 1970-01-01
  • 2019-10-22
相关资源
最近更新 更多