14

假设我有一个套接字:

std::shared_ptr<tcp::socket> socket( new tcp::socket(acceptor.get_io_service()) );
acceptor.async_accept( *socket, std::bind( handleAccept, this, std::placeholders::_1, socket, std::ref(acceptor)) );

我将一个weak_ptr存储到容器中的所述套接字中。我需要这个,因为我想让客户端请求其他客户端的列表,这样他们就可以互相发送消息。

clients_.insert(socket);  // pseudocode

然后我运行一些异步操作

socket->async_receive( boost::asio::buffer(&(*header), sizeof(Header))
    , 0
    , std::bind(handleReceiveHeader, this, std::placeholders::_1, std::placeholders::_2, header, socket));

如何检测连接何时关闭,以便我可以从容器中删除我的套接字?

clients_.erase(socket); // pseudocode
4

2 回答 2

23

TCP 套接字断开连接通常asioeof或 表示connection_reset。例如

  void async_receive(boost::system::error_code const& error,
                     size_t bytes_transferred)
  {
    if ((boost::asio::error::eof == error) ||
        (boost::asio::error::connection_reset == error))
    {
      // handle the disconnect.
    }
    else
    {
       // read the data 
    }
  }

boost::signals2尽管您始终可以将指向函数的指针传递给套接字类然后调用它,但我使用它来发出断开连接的信号。

请注意您的套接字和回调生命周期,请参阅:boost-async-functions-and-shared-ptrs

于 2013-11-10T16:17:01.557 回答
1

有很多选择,其中一些是:

  1. 当您存储weak_ptr在容器中时 - 它不会延长套接字的生命周期,因此当您的处理程序获取boost::asio::error::eof(或其他)时,它不会复制/移动shared_ptr,并且套接字将被删除(如果您没有任何其他shared_ptrs它)。因此,您可以执行以下操作:if(socket.expired()) clients_.erase(socket);

  2. 检查处理程序中的错误代码 - 它会指示连接何时关闭。使用此信息 - 您可以clients_.erase从处理程序本身调用。

你能举一个#2的例子吗?

它会是这样的:

socket->async_receive
(
    boost::asio::buffer(&(*header), sizeof(Header)), 0,
    [=, &clients_](const system::error_code& error, size_t bytes_transferred)
    {
        if(error) // or some specific code
        {
            clients_.erase(socket); // pseudocode
        }
        else
        {
            // continue, launch new operation, etc
        }
    }
);
于 2013-11-10T08:26:18.343 回答