如何确定是不是有数据可从 boost::asio 中的套接字读取?

Posted

技术标签:

【中文标题】如何确定是不是有数据可从 boost::asio 中的套接字读取?【英文标题】:How do I find out if there is data available to be read from a socket in boost::asio?如何确定是否有数据可从 boost::asio 中的套接字读取? 【发布时间】:2009-12-15 22:02:30 【问题描述】:

我正在使用 Boost ASIO 库编写 TCP 客户端程序。

当您连接时,协议以横幅行开头,后跟“\r\n” 我可以像 smtp 一样随时发送命令。

但是,服务器也可以在我不要求数据时向我发送数据,并且它以 '\r\n' 终止

我有这样一行来读取和解析初始连接横幅 这意味着,当我得到“\r\n”时停止阅读。

boost::asio::streambuf response_;
...
boost::asio::async_read_until(socket_, response_, "\r\n",
            boost::bind(&PumpServerClient::HandleReadBanner, this,
                boost::asio::placeholders::error));

但是在不同的时间我希望能够提出这个问题,是否有可用的数据?如果有,请阅读它直到“\r\n”。我觉得我需要一个 peek 功能,但我看不到它在哪里。

好的,也许我可以再次调用 async_read_until。但是考虑一下……它永远不会结束。 继续阅读调试出现一次。很明显,它一直在等待完成,但永远不会完成。

void client::HandleReadRequest(const boost::system::error_code& err)

    if (!err)
        // Got some data, print it out
        std::ostringstream ss;
        ss << &response_;

        std::cout << ss.str() << std::endl;

         // Keep reading...
        boost::asio::async_read_until(socket_, response_, "\r\n",
          boost::bind(&client::HandleReadRequest, this, boost::asio::placeholders::error));

        std::cout << "keep reading" << std::endl;
    
    else
    
        std::cout << "Error: " << err.message() << "\n";
    

好的,我想我现在明白了。我没有看到一个足够完整的示例来作为我的代码的基础。

看起来像调用:

boost::asio::async_read_until(socket_, 响应_,“\r\n”, boost::bind(&client::HandleReadRequest, 这, boost::asio::placeholders::error)); 表示当response_缓冲区中出现\r\n时,会调用函数HandleReadRequest。我只需要调用 async_read_until 一次。除非调用了写入请求,否则我需要再次读取...看来...好吧,至少我现在可以正常工作了。

【问题讨论】:

【参考方案1】:

看了documentation,我会选择socket_base::bytes_readable,如:

boost::asio::ip::tcp::socket socket(io_service); 
...
boost::asio::socket_base::bytes_readable command(true);
socket.io_control(command);
std::size_t bytes_readable = command.get();

【讨论】:

这很干净!【参考方案2】:

通常在 asio 中使用异步操作时,不需要“窥视”。当数据可用时,asio 将通过调用您提供的处理函数来告诉您。如果您的处理程序尚未被调用,则没有可用的数据。

如果你“窥视”套接字,我怀疑它不会像你期望的那样工作,因为数据将被 asio 读取并在可用时立即传递给读取处理程序,它只会“准备好在调用处理程序时读取”一小段时间。尽管只要套接字上没有启动async_read,它就可以工作。

对于您的async_read_until,您可能只想在调用读取处理程序时发布另一个读取请求。

【讨论】:

你的意思是你永远不会得到读取回调,或者读取回调被连续调用?如果是后者,可能是因为您没有在读取回调中检查错误情况。例如,read_handler(const boost::system::error_code&amp; e, ...) if (!e) async_read_until... 参见上面的示例代码。 HandleReadRequest 调用另一个 HandleReadRequest。更多数据被发送到它,但仍然没有出现 是的,不知何故完全错过了。 >_

以上是关于如何确定是不是有数据可从 boost::asio 中的套接字读取?的主要内容,如果未能解决你的问题,请参考以下文章

.NET(单声道)是不是有类似 boost::asio 的东西?

Boost::Asio : io_service.run() vs poll() 或者我如何在主循环中集成 boost::asio

boost::asio::strand 在 Ubuntu 11.04 (boost_all_dev 1.42) 上是不是损坏

BOOST ASIO POST HTTP REQUEST-标头和正文

如何使用Boost.Asio读取WHOLE char类型捕获的数据

std::bind 是不是应该与 boost::asio 兼容?