c++ - boost::asio::read() 永远阻塞

标签 c++ boost boost-asio

我正在尝试了解 Boost.asio 的工作原理。我编写了一个基本的服务器和客户端示例:

服务器.cpp

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

#define PORT 27015

using namespace boost::asio;
using ip::tcp;

std::string read(tcp::socket& socket) {
    boost::system::error_code error;
    boost::asio::streambuf buffer;
    boost::asio::read(socket, buffer, boost::asio::transfer_all(), error);
    if (error) {
        std::cerr << "read error: " << error.message() << "\n";
        return "ERROR";
    }
    else {
        std::string data = boost::asio::buffer_cast<const char*>(buffer.data());
        return data;
    }
}

void send(tcp::socket& socket, const std::string& message) {
    boost::system::error_code error;
    boost::asio::write(socket, boost::asio::buffer(message), error);
    if (error)
        std::cerr << "send error: " << error.message() << "\n";
    else
        std::cout << "sent \"" << message << "\" to the client" << "\n";
}

int main() {
    boost::asio::io_service io_service;

    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), PORT)); // create listener for new connection(s)
    tcp::socket socket(io_service); // socket creation

    std::cout << "awaiting connection..." << "\n";
    acceptor.accept(socket); // direct connection(s) to the socket we created
    std::cout << "accepted connection!" << "\n";

    std::string received = read(socket); // receive data
    std::cout << "received message: " << received << "\n";

    send(socket, "hello from server!"); // send data
}

客户端.cpp

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

#define PORT 27015

using namespace boost::asio;
using ip::tcp;

int main(int argc, char *argv[])
{
    boost::asio::io_service io_service;
    tcp::socket socket(io_service); // socket creation

    std::string server_ipv4_address = "192.168.1.2";
    std::cout << "connecting to server at " << server_ipv4_address << "\n";

    try {
        socket.connect(tcp::endpoint(boost::asio::ip::address::from_string(server_ipv4_address), PORT)); // connection
        std::cout << "connected!" << "\n";
    }
    catch (const boost::system::system_error& e) {
        std::cerr << "error while connecting: " << e.what() << "\n";
        return -1;
    }

    boost::system::error_code error; // error holder

    std::string message = "hello from client!!\n";
    boost::asio::write(socket, boost::asio::buffer(message), error); // send message to server
    if (error)
        std::cerr << "send failed: " << error.message() << "\n";
    else
        std::cout << "sent \"" << message << "\" to the server" << "\n";

    boost::asio::streambuf receive_buffer;
    boost::asio::read(socket, receive_buffer, boost::asio::transfer_all(), error); // receive from server
    if (error && error != boost::asio::error::eof)
        std::cerr << "receive failed: " << error.message() << "\n";
    else {
        std::string data = boost::asio::buffer_cast<const char*>(receive_buffer.data());
        std::cout << "received data: " << data << "\n";
    }
}

连接已正确建立,但来自服务器的 read() 函数会阻止程序,因为它没有从客户端接收数据,或者我调用它的方式有问题。这里的 boost::asio::read() 似乎有什么问题? 如果我将 boost::asio::readboost::asio::read_until 交换,一切正常,如下所示。为什么该功能在客户端可以正常使用,但在服务端却不行?

std::string read(tcp::socket& socket) {
    boost::system::error_code error;
    boost::asio::streambuf buffer;
    boost::asio::read_until(socket, buffer, "\n");
    std::string data = boost::asio::buffer_cast<const char*>(buffer.data());
    return data;
}

最佳答案

以完成条件读取transfer_all意味着它将继续读取,直到缓冲区已满或连接无效。

缓冲区“永远”不会满(因为它是动态缓冲区)。

这样就留下了客户端永远不会挂断的原因。

Everything works properly if I swap boost::asio::read with boost::asio::read_until as shown below.

正是如此。因为这样你就有了另一个停止阅读的理由。请注意,它仍然可能永远阻塞(当 '\n' 永远不会到达时)。

Why does the function work properly in the client but not in the server?

事实并非如此。这似乎是因为服务器显然确实关闭了连接(发出 EOF 信号)。 [您会注意到这一点,因为后续读取将返回 error_code boost::asio::error::eof。]

关于c++ - boost::asio::read() 永远阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66186306/

相关文章:

c++ - 具有自定义标量类型的特征值 : Matrix multiplication with custom type fails with `use of overloaded operator ' *' is ambiguous`

c++ - 在 *nix 上了解异步编程的基础知识

c++ - 如何实现 constexpr string_view 与数字的乘法

c++ - 有没有办法知道二进制文件/文件的特定部分此刻是否在内存中?

c++ - g++ 包括 boost 库

c++ - Boost Asio 多线程 TCP 同步服务器

c++ - 提升测试和异步 IO : memory access violation at address : no mapping at fault address

c++ - NITE2::UserTracker 在读取 oni 文件时崩溃

c++ - 从 std::tuple<some_types...> 开始创建子元组

c++ - boost::format 和 wchar_t