c++ - boost::asio readsome 函数似乎不起作用

标签 c++ boost boost-asio

我目前在使用 boost::asio 时遇到问题,我想像下面的代码一样编写和读取。写入工作正常,但读取总是返回零。其实我也发现每个网站都指的是

read_some

函数而不是

readsome

函数库中我的系统...

有人可以给我一些提示吗?

boost::asio::ip::tcp::iostream tcp_stream;
tcp_stream.connect("localhost", "12345");

while(1)
{
    char inp[6]={0,0,0,0,0,0};

    tcp_stream<<"Test"<<std::endl;//Works fine get it with netcat (nc -l 12345)

    size_t r = tcp_stream.readsome(inp,5);//Always 0

    //std::string a;
    //tcp_stream>>a; //Works but blocks and gives me all bytes it has.
    //std::cout<<a<<std::endl;

    //std::cout<<"RDBUF: "<<tcp_stream.rdbuf();
    //rdbuf blocks here, never resuming and outputting 
    //everything I write with netcat to command line...
    if(r>0)
    {
        std::cout<<inp<<std::endl;
    }

    else //<<< always goes here
    {
        std::cout<<"received nothing!"<<std::endl;


    }
    sleep(1);
}

我想要的是我从当前界面读取0-5个字节。 (非阻塞)

最佳答案

问题是 std::basic_istream<>::read_some()将从关联的 streambuf 读取的输入序列,以及 asio::basic_socket_streambuf 的输入序列包括已从套接字读取但尚未从流缓冲中使用的数据。它不包括无需阻塞即可从套接字读取的数据。[1]

要变通解决此行为,可以确定可读取的数据量而不阻塞 streambuf 及其底层套接字,然后发出 std::basic_istream<>read()。操作:

/// @brief Read up to `n` characters from `stream` and store them
///        into `buffer` without blocking.  This may not read all
///        of the requested amount of bytes.
template <typename... Args>
std::streamsize readsome(
  boost::asio::basic_socket_iostream<Args...>& stream,
  char* buffer,
  std::streamsize n)
{
  std::streamsize available =
    stream.rdbuf()->in_avail()     // available on input sequence
    + stream.rdbuf()->available(); // available on socket
  n = std::min(n, available);
  if (n == 0) return 0;

  stream.read(buffer, n);
  return n;
}

这是一个完整的例子demonstrating此功能:

#include <chrono>     // std::chrono::seconds
#include <iostream>   // std::cout, std::endl
#include <string>     // std::to_string
#include <thread>     // std::thread
#include <boost/asio.hpp>

/// @brief Read up to `n` characters from `stream` and store them
///        into `buffer` without blocking.  This may not read all
///        of the requested amount of bytes.
template <typename... Args>
std::streamsize readsome(
  boost::asio::basic_socket_iostream<Args...>& stream,
  char* buffer,
  std::streamsize n)
{
  std::streamsize available =
    stream.rdbuf()->in_avail()     // available on input sequence
    + stream.rdbuf()->available(); // available on socket
  n = std::min(n, available);
  if (n == 0) return 0;

  stream.read(buffer, n);
  return n;
}

int main()
{
  using boost::asio::ip::tcp;

  const std::array<char, 6> expected_data = {100, 101, 102, 103, 104, 105};

  // Create all I/O objects.
  boost::asio::io_service io_service;
  tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 0));
  tcp::socket socket(io_service);

  // Run stream in its own thread.
  std::thread client_thread(
    [&]
    {
      // Connect the stream to the acceptor.
      auto endpoint = acceptor.local_endpoint();
      tcp::iostream stream(endpoint.address().to_string(),
                           std::to_string(endpoint.port()));

      // Block until 6 bytes are available.
      while (stream.rdbuf()->available() < 6)
      {
        std::this_thread::sleep_for(std::chrono::seconds(1));
      }

      // Read 1 byte out of the 6 avaialble.
      std::array<char, 6> actual_data{};
      auto bytes_transferred = readsome(stream, begin(actual_data), 1);
      assert(bytes_transferred == 1);
      assert(std::equal(
        begin(actual_data),
        begin(actual_data) + bytes_transferred,
        begin(expected_data)));

      // Attempt to read 6 bytes, although only 5 are available.
      bytes_transferred = readsome(stream, begin(actual_data),
                                   sizeof actual_data);
      assert(bytes_transferred == 5);
      assert(std::equal(
        begin(actual_data),
        begin(actual_data) + bytes_transferred,
        begin(expected_data) + 1));

      // Attempt to read 6 more bytes, even though 0 bytes are available.
      bytes_transferred = readsome(stream, begin(actual_data),
                                   sizeof actual_data);
      assert(bytes_transferred == 0);
    });

  // Connect the sockets then write to the stream.
  acceptor.accept(socket);
  boost::asio::write(socket, boost::asio::buffer(expected_data));

  // Wait for the stream to complete.
  client_thread.join();
}

<子>1。 tcp::stream 文档及其相关类没有很好的记录。我不够精通,不知道这种行为是故意的、错误的,还是只是被忽视了。当前 networking-ts draft 中的文档仍然相当简洁.

关于c++ - boost::asio readsome 函数似乎不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38037991/

相关文章:

c++ - OpenCV imshow 错误? - 像素颜色

c++ - 使 boost::fast_pool_allocator 与可变参数模板一起工作 (emplace)

c++ - 如何在 boost 1.57 中安装 boost 模块(应用程序和 dll)

c++ - 如何使用 boost 从 com 端口读取未定义数量的字节?

c++ - 如何使用boost::beast连续流式传输文件

c++ - 作为非成员的算术复合运算符重载

c++ - Winform 不在设计器中显示

c++ - 一直说 uint16 未声明

c++ - 使用 Boost 基本截止时间计时器来调用类方法

C++:boost::asio:async_resolve() 不起作用(使用 lambda 函数),但 resolve() 起作用