c++ - boost asio async_read() 似乎跳过了一些空值

标签 c++ c++14 boost-asio

我对一个简单的 boost asio TCP 对话有点疯狂。

我有一个服务器和一个客户端。我使用长度前缀的消息。客户端发送“一”,服务器响应“二”。所以这就是我看到的情况:

客户端发送,服务器接收,00 00 00 03 6F 6E 65 (== 0x0003 one).

服务器通过发送 00 00 00 03 74 77 6F(== 0x0003 二)来响应。

现在这是非常奇怪的地方(下面的代码)。如果客户端读取四个字节,我希望它得到 00 00 00 03。如果它显示为 7,我希望看到 00 00 00 03 74 77 6F。 (实际上,它将读取四个(长度 header ),然后是三个(主体)。)

但我实际看到的是,如果我一次读取七个,我会看到 00 00 00 03 74 77 6F,如果我只要求四个,我会看到 74 77 6F 03。这对我来说没有任何意义。

这是我用来接收它的代码(减去一些打印语句等):

const int kTcpHeaderSize = 4;
const int kTcpMessageSize = 2048;
std::array<char, kTcpMessageSize + kTcpHeaderSize> receive_buffer_;

void TcpConnection::ReceiveHeader() {
    boost::asio::async_read(
        socket_, boost::asio::buffer(receive_buffer_, kTcpHeaderSize),
        [this](boost::system::error_code error_code,
               std::size_t received_length) {
            if (error_code) {
                LOG_WARNING << "Header read error: " << error_code;
                socket_.close();  // TODO: Recover better.
                return;
            }
            if (received_length != kTcpHeaderSize) {
                LOG_ERROR << "Header length " << received_length
                          << " != " << kTcpHeaderSize;
                socket_.close();  // TODO: Recover better.
                return;
            }
            uint32_t read_length_network;
            memcpy(&read_length_network, receive_buffer_.data(),
                   kTcpHeaderSize);
            uint32_t read_length = ntohl(read_length_network);
            // Error: read_length is in the billions.
            ReceiveBody(read_length);
        });
}

请注意,kTcpHeaderSize 为 4。如果我将其更改为 7(这没有任何意义,只是为了实验),我会看到我期望的 7 字节流。当它为 4 时,我看到的流不是我期望的前四个字节。

任何指示我做错了什么?

最佳答案

据我在您的代码中看到的,它应该根据 async_read documentation 工作:

The asynchronous operation will continue until one of the following conditions is true:

  • The supplied buffers are full. That is, the bytes transferred is equal to the sum of the buffer sizes.
  • An error occurred.

但是请看底部的注释:

This overload is equivalent to calling:

boost::asio::async_read( s, buffers, boost::asio::transfer_all(), handler);

它看起来像 transfer_all条件可能是唯一检查的内容。

尝试使用 transfer_exactly条件,如果它确实有效,请在 https://github.com/boostorg/asio/issues 上报告问题.

关于c++ - boost asio async_read() 似乎跳过了一些空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53209927/

相关文章:

c++ - 通过在 move 赋值运算符中使用 std::swap 来重用析构函数逻辑是否有意义?

c++ - 这个双向链表代码怎么解释呢?

c++ - 按模式分割 vector

c++ - 重载 = 运算符和名称隐藏

c++ - 使用 C++ 从 HTTPS 请求 JSON 数据?

c++ - 如何在 Visual Studio 代码中编译和运行 C++ 源文件

c++ - 使用命名空间和 using 指令不适用于 std::enable_if_t

c++ - 用于多播的 boost::asio 和 socket.h 之间的区别

javascript - 像curl一样发送post数据

c++ - 对 c 结构进行排序