【问题标题】:How to detect when a boost tcp socket disconnects如何检测 boost tcp 套接字何时断开连接
【发布时间】:2013-11-22 03:27:27
【问题描述】:

假设我有一个套接字:

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

【问题讨论】:

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


    【解决方案1】:

    TCP 套接字断开连接通常由eofconnection_resetasio 中发出信号。例如

      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

    【讨论】:

    • 我发现这确实有效,我收到错误“connection_reset”。但是,在文档中我注意到另一个错误代码“connection_aborted”。是不是也需要处理这个错误码?
    • 这是一个有用的链接@aCuria。错误代码的另一个来源是文件boost/system/error_code.hpp。至于“connection_aborted”错误,我在我的应用程序中没有看到它,但测试它也没有什么坏处。
    • 酷。但是,如果您不想接收任何数据怎么办?我唯一想知道的是连接是打开还是关闭,甚至没有尝试读取远程端发送的任何内容。 asio中好像没有这样的API。
    • @OlegAndriyanov 您的要求听起来很不寻常。它是一种通信协议,所以它发送和接收数据是它存在的理由......
    【解决方案2】:

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

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

    【讨论】:

    • 你能举一个#2的例子吗?
    • @aCuria 添加了示例。
    • 我认为我不应该删除任何错误,但快速的谷歌搜索似乎并没有抛出专门针对 async_receive 的错误代码列表。
    • 与关闭连接相关的错误:boost::asio::error::eof,与重置连接相关的错误:boost::asio::error::connection_reset
    猜你喜欢
    • 2011-09-18
    • 2020-07-04
    • 2013-11-16
    • 2012-12-10
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 2013-07-22
    相关资源
    最近更新 更多