如何检测通过boost :: asio_stream_async连接的特定tcp流是否已关闭?

时间:2016-06-14 07:38:14

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

我的C++ library正在使用boost :: asio_connector_async列表进行tcp连接 问题是,如果其中一个流由于某种原因而关闭,则不会通过boost向我的库发送有关相同信息的信息。 因此,我的库永远无法检测哪些流已关闭,哪些流仍处于打开状态。 我的库包含类boost :: asio_connector_async(通过连接器名称)的对象,并以这种方式连接到主机端口:

connector.async_connect(hostname.c_str(), qport.c_str(),          boost::bind(bc::asio_bind_sock_chan<pubsub_channel,pubsub_channel::text_marshaler_registry>(),boost::ref(chan), boost::ref(mar_reg), hostname, qport, channel_logger, _1, _2, _3));

关闭特定的<host,port>流时,会从文件boost::asio_connector_async::on_stream_closed内部调用函数asio_stream_async.hpp

void on_stream_closed(void * sp, const std::string & host, const std::string port) {
        boost::channel::logger_stream(logger_) << "boost::channel::asio_connector_async::on_stream_closed - " << host << ":" << port << ": stream 0x" << sp << " closed";
      }

我想以这样的方式将我的库附加到boost::asio_connector_async::on_stream_closed,无论何时调用此特定函数,我的库中的某些函数也会被调用,以便我的库知道哪个特定流已关闭然后应该尝试重新连接该流 请建议我如何实现同样的目标?在没有修改boost库的情况下我无法想到实现这一点(我不应该这样做) 如果还有其他方法可以检测到已关闭的连接,请同时向我推荐。

我是这种网络编程的新手,因此需要相同的帮助。 提前致谢

2 个答案:

答案 0 :(得分:0)

客户断开连接需要在handle_read回调(或您提供的任何名称)中处理。

将从流中读取0个字节来调用异步读取回调。或者您也可以检查asio::error::connection_resetasio::error::eof的系统错误代码,或者只是bytes_read == 0(我建议您也做其他提到的测试。)

一个例子(来自asio示例:chat_client.cpp)

asio::async_connect(socket_, endpoints,
        [this](std::error_code ec, tcp::endpoint)
        {
          if (!ec)
          {
            do_read_header();
          }
         //ATTN: This is where you should handle failed socket connection
        });

void do_read_header()
  {
    asio::async_read(socket_,
        asio::buffer(read_msg_.data(), chat_message::header_length),
        [this](std::error_code ec, std::size_t /*length*/)
        {
          if (!ec && read_msg_.decode_header())
          {
            do_read_body();
          }
          else
          {
            socket_.close();
          }
        });
  }

ATTN处理程序中查找async_connect条评论。

答案 1 :(得分:0)

如果检测到连接失败,asio发出的任何调用都将显示错误。

然而,这并不意味着远程端仍然可以访问。一旦数据被放入内核队列,TCP发送就会完成。检测到故障可能需要很长时间才能被检测到。

如果连接保真度很重要,则需要在会话层协议中设计一个echo请求。