我已经使用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而没有任何阻塞呼叫?
答案 0 :(得分:0)
我要说几句话:
调用io_service :: run_one。现在,如果我直接使用async_read, 将阻塞对run_one的调用,直到读取某些内容或 错误发生
您可以通过创建伪造的work<>
对象并将其发布到io_service
队列中来轻松地颠覆这种阻塞行为,因此只要有要执行的处理程序,轮询就不会等待任何事件:只需立即返回。
谈论size_t nbytes=socket_.available(error);
; avilable()
返回可读取的字节数(可能没有阻塞),如注释中所述:也许,您需要读取就绪字节才能看到EOF,但是avilable()
没有任何内容与之相关。