boost::asio::async_read_until 没有阅读所有消息

boost::asio::async_read_until does not read all message

boost::asio::async_read_until 没有读取所有数据,并挂在消息中间。

    boost::asio::async_read_until(socket, response, "\n", boost::asio::placeholders::error));
                        [&](const boost::system::error_code &err2, std::size_t lenght)
                        {
                            RUN_CHECK;
                            if (!err2)
                            {
                                RUN_CHECK;
                                std::string r =  this->response_get();
    /*
    .. do stuff here
    */

                            }
                            else
                            {
                                report_error(err2);
                            }
}

知道出了什么问题吗?在到达“\n”之前 async_read_until 不应该读取吗?

                  std::string r = this->response_get();

无论您在 response_get() 中做什么,您都没有 正确使用 length。这意味着接收到的超出定界符 ("\n") 的任何字符也可能被消耗掉,这意味着下一次读取将缺少开头。

另一个可能出现的问题是您的缓冲区不是动态的(例如 asio::streambuf)并且您没有预留足够的容量。然后异步读取将在缓冲区已填满时完成,即使未收到分隔符也是如此。

None这个解释"hang"。如果您观察到挂起,请检查您的服务器(发送端)和/或网络基础设施(使用网络监控工具检查消息是否确实到达)。

这里是代码的快速修正 self-contained:

#include <boost/asio.hpp>
#include <iostream>

#define RUN_CHECK                                                                                                      \
    do {                                                                                                               \
        std::cout << "Here:" << __LINE__ << "\n";                                                                      \
    } while (0)

struct X {
    boost::asio::io_service io;
    boost::asio::ip::tcp::socket socket{io};

    X() {
        socket.connect({ {}, 6767 });
    }

    boost::asio::streambuf response;

    void foo() {
        boost::asio::async_read_until(socket, response, "\n",
              [&](const boost::system::error_code &ec, std::size_t length) {
                  RUN_CHECK;
                  if (!ec) {
                      RUN_CHECK;
                      std::string r = this->response_get(length);
                      /*
                      .. do stuff here
                      */

                  } else {
                      report_error(ec);
                  }
              });
    }

    std::string response_get(std::size_t length) {
        std::string result;
        std::copy_n(boost::asio::buffers_begin(response.data()), length, back_inserter(result));
        return result;
    }

    void report_error(boost::system::error_code ec) {
        std::cout << "Error: " << ec.message() << "\n";
    }
};

int main() {
    X x;
    x.foo();

    x.io.run();
}