boost :: asio :: async_read_until不读取所有消息

时间:2018-04-10 15:07:02

标签: c++ boost asio

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读取吗?

1 个答案:

答案 0 :(得分:0)

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

无论您在response_get()中做了什么,都使用length正确 。这意味着在分隔符("\n")之外收到的任何字符都可能被消耗,这意味着下次读取将缺少开始。

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

这些都没有解释"挂起"。如果您发现挂起,请检查您的服务器(发送方)和/或网络基础设施(使用网络监控工具检查该消息是否实际到达)。

这里有一个快速修复的代码是自包含的:

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