簡體   English   中英

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

[英]boost::asio::read() blocks forever

我正在嘗試了解 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() function 阻止了程序,因為它沒有從客戶端接收數據,或者我調用它的方式有問題。 這里的boost::asio::read()似乎有什么問題? 如果我將boost::asio::readboost::asio::read_until交換,一切正常,如下所示。 為什么function在客戶端可以正常工作,而在服務端不行?

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讀取意味着它將繼續讀取,直到緩沖區已滿或連接變為無效。

緩沖區“永遠不會”滿(因為它是 DynamicBuffer)。

這樣就留下了客戶端永遠不會掛斷的原因。

如果我將 boost::asio::read 與 boost::asio::read_until 交換,一切正常,如下所示。

確切地。 因為那樣你就有另一個理由停止閱讀。 請注意,它仍然可能永遠阻塞(當'\n'永遠不會到達時)。

為什么function在客戶端可以正常工作,而在服務端不行?

它沒有。 這似乎是因為服務器顯然確實關閉了連接(發信號通知 EOF)。 [您會注意到這一點,因為后續讀取將返回 error_code boost::asio::error::eof。]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM