如何在Boost Asio中检测套接字上的关闭连接而不会阻止调用

时间:2019-06-06 07:16:29

标签: c++ sockets boost-asio eof

我已经使用boost asio编写了一个tcp通信方案,如果我为io_service::run()使用了单独的线程,那么它的工作原理还不错。但是,该通信器也应作为MPI并行程序的一部分使用(请不要对此表示怀疑),在这种情况下,分叉和线程化不是一个好主意,并且可能是不允许的。

因此,通信器具有调用work()的功能io_service::run_one。现在,如果我直接使用async_read,则会阻塞对run_one的调用,直到读取某些内容或发生错误为止。因此,我编写了下面显示的check_available函数,首先在函数async_read中调用read_message_header之前,先检查套接字上是否有东西。

这也可以顺利进行,直到对等方关闭连接。不幸的是,socket::available(error)似乎没有将其标记为eof错误,就像async_read中的情况一样,它返回0作为可用字节数,因此从未调用read_message_header ,然后可以检测到eof。同样,检查socket::is_open()对此不起作用,因为在此实例上,只有对等方的套接字已关闭,而接收方套接字未关闭。

void TCPConnection::check_availble() {
    if(! socket_.is_open()) {
        handle_read_error(boost::asio::error::eof);
    }
    boost::system::error_code error;
    size_t nbytes=socket_.available(error); // does not detect the eof
    if(error)
        handle_read_error(error);
    if(nbytes>0)
        read_message_header();
    else
        socket_.get_io_service().post(
                boost::bind(
                        &TCPConnection::check_availble,
                        shared_from_this()
                )
        );
}

有没有一种方法可以检测到eof而没有任何阻塞呼叫?

1 个答案:

答案 0 :(得分:0)

我要说几句话:

  

调用io_service :: run_one。现在,如果我直接使用async_read,   将阻塞对run_one的调用,直到读取某些内容或   错误发生

您可以通过创建伪造的work<>对象并将其发布到io_service队列中来轻松地颠覆这种阻塞行为,因此只要有要执行的处理程序,轮询就不会等待任何事件:只需立即返回。

谈论size_t nbytes=socket_.available(error);avilable()返回可读取的字节数(可能没有阻塞),如注释中所述:也许,您需要读取就绪字节才能看到EOF,但是avilable()没有任何内容与之相关。