简体   繁体   English

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

[英]boost::asio readsome function does not seem to work

I am currently experiencing troubles using boost::asio, I want to write and read like in the following piece of code. 我目前在使用boost :: asio遇到麻烦,我想像下面的代码那样进行读写。 Write works fine, but reading always returns zero. 写入工作正常,但读取始终返回零。 Actually I also found out that every site refers to the 实际上,我还发现每个站点都引用了

read_some read_some

function instead of the 功能而不是

readsome 好看的

function I have on my system in the library ... 我的系统在图书馆的功能...

Anybody who can give me a hint on this? 有人可以给我提示吗?

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);
}

What I would like to have is that I read 0-5 bytes from the current interface. 我想从当前接口读取0-5个字节。 (non-blocking) (非阻塞)

The issue is that std::basic_istream<>::read_some() will read from the associated streambuf 's input sequence, and the asio::basic_socket_streambuf 's input sequence includes data that has been read from the socket, but not yet consumed from the streambuf. 问题是std::basic_istream<>::read_some()将从关联的streambuf的输入序列中读取,而asio::basic_socket_streambuf的输入序列包含已从套接字读取但尚未使用的数据从streambuf。 It does not include data that is available to be read from the socket without blocking. 它不包括可无阻塞地从套接字读取的数据。 [1] [1]

To work around this behavior, one could determine the amount of data available to be read without blocking from both the streambuf and its underlying socket, then issue a std::basic_istream<>read() operation: 要解决此问题,可以确定可读取的数据量,而不会阻塞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;
}

Here is a complete example demonstrating this functionality: 这是演示此功能的完整示例:

#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. The tcp::stream documentation and its related classes are not well documented. 1. tcp::stream文档及其相关类的文档不完整。 I am not versed enough to know if this behavior is intentional, a bug, or has merely been overlooked. 我不了解这种行为是故意的,错误的,还是只是被忽略了。 The documentation still remains fairly terse in the current networking-ts draft . 在当前的网络-ts草案中 ,文档仍然很简洁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM