boost::asio::read() 永远阻塞
boost::asio::read() blocks forever
我正在尝试了解 Boost.asio 的工作原理。我已经编写了一个基本的服务器和客户端示例:
server.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
}
client.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::read
与 boost::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;
}
Read with the completion condition transfer_all
表示它将一直读取直到缓冲区已满或连接失效。
缓冲区“永远不会”满(因为它是 DynamicBuffer)。
这样就留下了客户端永远不会挂断的原因。
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 信号)。 [你会注意到这一点,因为随后的阅读会 return error_code boost::asio::error::eof。]
我正在尝试了解 Boost.asio 的工作原理。我已经编写了一个基本的服务器和客户端示例:
server.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
}
client.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::read
与 boost::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;
}
Read with the completion condition transfer_all
表示它将一直读取直到缓冲区已满或连接失效。
缓冲区“永远不会”满(因为它是 DynamicBuffer)。
这样就留下了客户端永远不会挂断的原因。
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 信号)。 [你会注意到这一点,因为随后的阅读会 return error_code boost::asio::error::eof。]