boost::asio::read 函数挂起

Posted

技术标签:

【中文标题】boost::asio::read 函数挂起【英文标题】:boost::asio::read function hanging 【发布时间】:2016-04-17 15:35:02 【问题描述】:

如果有人可以帮助我,我无法理解 boost::asio::read 函数在 boost asio 中是如何工作的。在 boost 的示例中,他们让它在收到消息之前声明缓冲区大小,这是没有意义的(我怎么知道在读取消息之前要读取多少字节?)

我试过这段代码,但它只是挂起

  boost::asio::io_service io_service;

  tcp::resolver resolver(io_service);
  tcp::resolver::query query(tcp::v4(), "localhost", "3000");
  tcp::resolver::iterator iterator = resolver.resolve(query);

  tcp::socket sock(io_service);
  boost::asio::connect(sock, iterator);
  cout << "read start" << endl;
  boost::system::error_code err_code;

  // Read from client.
  boost::asio::streambuf read_buffer;
  int bytes_transferred = boost::asio::read(sock, read_buffer, err_code);
  std::cout << "Read: " << make_string(read_buffer) << std::endl;
  read_buffer.consume(bytes_transferred); // Remove data that was read.

【问题讨论】:

是“挂起”还是等待更多数据进来 它正在等待数据进入,但我如何在读取它之前告诉它要读取的字节数? 这是套接字(和 TCP/IP)的一个棘手方面。他们无法告诉您有多少字节的数据入站。你必须用协议的性质来判断。如果您创建自己的协议,您应该有一些消息结束模式(例如,“\n”)或指示后面有多少字节的消息头。 【参考方案1】:

通常,你从协议的定义中就知道要读取多少字节。

在相反的情况下,您必须逐个读取字节并观察错误代码以在连接、文件等结束时停止。

Boost.Asio 中的同步方法(例如read)非常适合简短的示例,但在实际用例中,您应该更喜欢异步版本async_read,它允许您取消或只需等待下一个数据块而不阻塞您的程序。

【讨论】:

【参考方案2】:

我也遇到了同样的问题。似乎 boost::asio::read 应该挂在那里,直到连接的客户端关闭。相反,您可以像这样使用socket.read_some

using boost::asio::ip::tcp;
try 
    boost::asio::io_service io_service;

    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 9999));

    for (;;) 
        tcp::socket socket(io_service);
        acceptor.accept(socket);

        std::string message = "server received!\n";

        boost::system::error_code error_code;
        boost::asio::streambuf stream_buf;

        std::vector<char> buf(1024);
        size_t len = socket.read_some(boost::asio::buffer(buf), error_code);
        std::string received_filename(buf.begin(), buf.end());
        received_filename.resize(len);
        if (error_code) 
            std::cout << "error status: " << error_code.message() << std::endl;
        

        boost::asio::write(socket, boost::asio::buffer(message), error_code);
        if (error_code) 
            std::cout << "error status: " << error_code.message() << std::endl;
        
        query_database(tree, received_filename, output_folder, db_image_filenames);
    

catch (std::exception& e) 
    std::cerr << e.what() << std::endl;

这将立即从客户端获取消息,并带有相对短的消息。希望对您有所帮助。

【讨论】:

以上是关于boost::asio::read 函数挂起的主要内容,如果未能解决你的问题,请参考以下文章

使用 boost::asio read_some() 函数时替代 std::array,boost::array 在 read_some() 函数调用时崩溃

boost::asio::async_read_until 与自定义匹配条件运算符重载混淆

传递给 boost::asio::async_read_some 的回调从未在 boost::asio::read_some 返回数据的使用中调用

当 streambuf 由先前的 async_read 填充时, boost::asio::async_read 进入 boost::asio::streambuf 块

boost::asio::read() 永远阻塞

Boost asio - 从标准输入异步读取已建立的字符数