Asio 没有收到来自远程系统的回复

Asio does not catch reply from remote system

我正在编写一个应该侦听域套接字的客户端。我打开同步连接,进行同步写入,我知道服务器发送了有效响应,因为我在套接字上使用 socat 到 eavesdrop

除了我的 asio::read() 被调用但从未 returns 任何数据。我传递给它的缓冲区总是空的。这是我的代码:

void operator>>(const vector<unsigned char> input, Socket &socket) {
      const size_t size = input.size();
      const size_t bytes = asio::write(socket.connection_socket, asio::buffer(input, size));
      if (bytes != size) {
        const std::error_code ec;
        throw std::system_error(ec, fmt::format("Tried to send {0} bytes but sent {1} instead.", size, bytes));
      }
      string buffer;
      asio::read(socket.connection_socket, asio::buffer(buffer));
      std::cerr << buffer << std::endl;
    }

这些是我用来连接到套接字的属性:

io_service run_loop;
stream_protocol::socket connection_socket;
datagram_protocol::endpoint domain_socket_ep;

Socket 是一个简单的 class,它包装了所有 Asio 代码,其中声明了上面的运算符重载。

asio::read 函数将读取 最多 asio::buffer_size(asio::buffer(buffer)) 个字节。在你的情况下 buffer 是空的,所以它最多读取零字节。

Asio 永远不会调整您传递给它的缓冲区的大小,因此您需要将 buffer 调整为您期望接收的最大大小。

此外,asio::read 函数实际读取的字节可能少于输入缓冲区的大小。它读取的实际大小从该函数返回。因此,如果你想 read/write 恰好可以放入缓冲区的字节数,你需要做这样的事情:

void read_to_buffer(asio::ip::tcp::socket& s, asio::buffer buffer) {
    size_t read = 0;
    size_t n = asio::buffer_size(buffer);
    while (read < n) {
        read += asio::read(s, buffer + read));
    }
}

void write_from_buffer(asio::ip::tcp::socket& s, asio::buffer buffer) {
    size_t written = 0;
    size_t n = asio::buffer_size(buffer);
    while (written < n) {
        written += asio::write(s, buffer + written));
    }
}

void operator>>(const vector<unsigned char> input, Socket &socket) {
      // TODO: convert between host and network byte order
      auto& s = socket.connection_socket;
      {
        const uint32_t size = input.size();
        write_from_buffer(s, asio::buffer(&size, sizeof(size));
        write_from_buffer(s, asio::buffer(input));
      }
      {
        uint32_t size = 0;
        read_to_buffer(s, asio::buffer(&size, sizeof(size)));
        string payload(size, 'x');
        read_to_buffer(s, asio::buffer(payload));
        std::cerr << payload << std::endl;
      }
}