2013-11-10 71 views
11

假设我有一个插座如何检测。我需要这个,因为我想让客户端请求其他客户端的列表,这样他们就可以向对方发送消息。当升压TCP套接字断开

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 

回答

14

TCP套接字断开通常在asio信号。例如。

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

+2

可以在此处找到错误列表:http:// www.boost.org/doc/libs/1_44_0/doc/html/boost_asio/reference/error__basic_errors.html – aCuria

+0

我发现这确实有效,我得到错误“connection_reset”。但是,在文档中,我注意到另一个错误代码“connection_aborted”。是否有必要处理这个错误代码? – aCuria

+0

这是一个有用的链接@aCuria。错误代码的另一个来源是文件'boost/system/error_code.hpp'。至于“connection_aborted”错误,我没有在我的应用程序中看到它,但测试它也没有什么坏处。 – kenba

1

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

  1. 正如你存储weak_ptr集装箱 - 它不会延长插座的使用寿命,所以当你的处理程序将得到boost::asio::error::eof(或其他) ,它不会复制/移动shared_ptr,并且套接字将被删除(如果您没有任何其他shared_ptr s)。因此,您可以执行如下操作:if(socket.expired()) clients_.erase(socket);

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

Could you give an example of #2?

这将是这样的:由eofconnection_reset

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

你能给的#2的例子吗? – aCuria

+0

@aCuria新增示例。 –

+0

我不认为我应该擦除任何错误,但快速谷歌搜索似乎并没有专门为async_receive提供错误代码列表。 – aCuria