Boost asio 获取“错误代码:125 操作已取消”
Boost asio getting `Error Code : 125 Operation cancelled`
我只是想用 acceptor socket 接受传入请求,当它进入 async_accept 时它抛出一个错误,我不确定是什么导致了错误。问题是我什至没有从客户端发送请求,但由于某种原因它仍然进入 async_accept 处理程序,这是导致错误
main.cpp
#include <iostream>
#include "server.hpp"
#include "connection.hpp"
class Connection;
int main(){
using Server_ = Server<Connection>;
auto server = std::make_unique<Server_>(8989);
server->start();
}
server.hpp
#pragma once
#include <thread>
#include <boost/asio.hpp>
template <typename Connection>
class Server{
using shared_connection = std::shared_ptr<Connection>;
private:
unsigned short port_;
std::thread io_thread_;
boost::asio::io_context ioc_;
boost::asio::io_context::work work_;
boost::asio::ip::tcp::endpoint endpoint_;
boost::asio::ip::tcp::acceptor acceptor_;
void handle_new_request(shared_connection connection, const system::error_code &ec){
if(!ec){
connection->start_operation();
}else{
error::print(ec);
return;
}
}
public:
explicit Server(unsigned short port)
: acceptor_(ioc_)
, work_(ioc_)
, port_(port)
, endpoint_(asio::ip::tcp::v4(), port) {
io_thread_ = std::move(std::thread([&]{ ioc_.run(); }));
io_thread_.join();
}
~Server() {
if(acceptor_.is_open())
acceptor_.close();
io_thread_.join();
}
void start(){
using namespace asio::ip;
system::error_code ec;
// creates an actual operating system socket
acceptor_.open(endpoint_.protocol(),ec);
acceptor_.set_option(tcp::acceptor::reuse_address(true),ec);
// binds to the endpoint
acceptor_.bind(endpoint_,ec);
if(!ec){
std::cout << "Listening for requests from port " << port_ << std::endl;
acceptor_.listen();
}else{
error::print(ec);
return;
}
shared_connection connection = std::make_shared<Connection>(ioc_);
acceptor_.async_accept(connection->sock_,[=](system::error_code ec){
handle_new_request(connection,ec);
});
}
};
connection.hpp
#pragma once
#include <memory>
#include <boost/asio.hpp>
class Connection : public std::enable_shared_from_this<Connection> {
using shared_connection = std::shared_ptr<Connection>;
std::vector<char> buffer_space_;
private:
boost::asio::mutable_buffers_1 buffer_;
boost::asio::io_context& ioc_;
public:
boost::asio::ip::tcp::socket sock_;
explicit Connection(boost::asio::io_context &context,const int &size = 1024)
: ioc_(context)
, sock_(context)
, buffer_space_(size)
, buffer_(buffer_space_.data(),size){}
~Connection(){ if(sock_.is_open()) sock_.close(); }
void start_operation(){
if(sock_.is_open()){
sock_.async_read_some(buffer_,[me = shared_from_this()](const system::error_code &ec, std::size_t bytes){
if(!ec){
for(int i=0;i<bytes;++i)
std::cout << me->buffer_space_[i];
std::cout << std::endl;
me->start_operation();
}else{
error::print(ec);
return;
}
});
}
}
};
error.hpp
#pragma once
#include <iostream>
#include <boost/system/error_code.hpp>
namespace error {
inline void print(const boost::system::error_code &ec){
std::cerr << "Error Code : " << ec.value() << ", Message : " << ec.message() << std::endl;
}
}
如有任何帮助,我们将不胜感激。谢谢!
错误在于析构函数中的 io_thread_.run()
会在那时销毁套接字对象
int main(){
using Server_ = Server<Connection>;
auto server = std::make_unique<Server_>(8989);
server->start();
}
server
将调用删除器,它在退出 main 时销毁 Server_
。您想在退出 main 之前加入任何线程或等待服务器关闭。
在你的情况下,你会加入 iothread,就像你尝试做的那样。
但是,您在服务器构造函数中执行此操作:
explicit Server(unsigned short port)
: acceptor_(ioc_)
, work_(ioc_)
, port_(port)
, endpoint_(asio::ip::tcp::v4(), port)
{
io_thread_ = std::move(std::thread([&] { ioc_.run(); }));
io_thread_.join();
}
I can't really figure out how this would not hang indefinitely due to the work_. On tangentially related observation is that work_
is NOT initilaized before ioc_
(or thread_
) because initialization happens in order of member declaration instead of order in which the initializers appear. You will want to fix the declaration order regardless:
boost::asio::io_context ioc_;
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::io_context::work work_;
unsigned short port_;
boost::asio::ip::tcp::endpoint endpoint_;
std::thread io_thread_;
Similarly in Connection
:
private:
boost::asio::io_context& ioc_;
public:
boost::asio::ip::tcp::socket sock_;
private:
std::vector<char> buffer_space_;
boost::asio::mutable_buffers_1 buffer_;
固定演示
#include <iostream>
#include <boost/system/error_code.hpp>
namespace error {
inline void print(const boost::system::error_code& ec)
{
std::cerr << "Error Code : " << ec.value()
<< ", Message : " << ec.message() << std::endl;
}
}
#include <memory>
#include <boost/asio.hpp>
class Connection : public std::enable_shared_from_this<Connection> {
using shared_connection = std::shared_ptr<Connection>;
private:
boost::asio::io_context& ioc_;
public:
boost::asio::ip::tcp::socket sock_;
private:
std::vector<char> buffer_space_;
boost::asio::mutable_buffers_1 buffer_;
public:
explicit Connection(
boost::asio::io_context& context, const int& size = 1024)
: ioc_(context)
, sock_(context)
, buffer_space_(size)
, buffer_(buffer_space_.data(), size)
{
}
void start_operation()
{
if (sock_.is_open()) {
sock_.async_read_some(buffer_,
[me = shared_from_this()](
const boost::system::error_code& ec, std::size_t bytes) {
if (!ec) {
for (size_t i = 0; i < bytes; ++i) {
std::cout << me->buffer_space_[i];
}
std::cout << std::endl;
me->start_operation();
} else {
error::print(ec);
return;
}
});
}
}
};
#include <thread>
#include <boost/asio.hpp>
template <typename Connection> class Server {
using shared_connection = std::shared_ptr<Connection>;
private:
boost::asio::io_context ioc_;
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>
work_ {ioc_.get_executor()};
uint16_t port_;
boost::asio::ip::tcp::endpoint endpoint_;
std::thread io_thread_;
void handle_new_request(
shared_connection connection, const boost::system::error_code& ec)
{
if (!ec) {
connection->start_operation();
} else {
error::print(ec);
return;
}
}
public:
explicit Server(uint16_t port)
: acceptor_(ioc_)
, port_(port)
, endpoint_(boost::asio::ip::tcp::v4(), port)
, io_thread_([&] { ioc_.run(); })
{ ; }
~Server()
{
if (acceptor_.is_open()) {
boost::system::error_code ec;
acceptor_.cancel(ec);
//acceptor_.close(ec);
}
work_.reset();
io_thread_.join();
}
void start()
{
using boost::asio::ip::tcp;
boost::system::error_code ec;
// creates an actual operating system socket
acceptor_.open(endpoint_.protocol(), ec);
acceptor_.set_option(tcp::acceptor::reuse_address(true), ec);
// binds to the endpoint
acceptor_.bind(endpoint_, ec);
if (!ec) {
std::cout << "Listening for requests from port " << port_
<< std::endl;
acceptor_.listen();
} else {
error::print(ec);
return;
}
shared_connection connection = std::make_shared<Connection>(ioc_);
acceptor_.async_accept(
connection->sock_, [=, this](boost::system::error_code ec) {
handle_new_request(connection, ec);
});
}
};
#include <iostream>
//#include "server.hpp"
//#include "connection.hpp"
using namespace std::chrono_literals;
class Connection;
int main()
{
using Server_ = Server<Connection>;
auto server = std::make_unique<Server_>(8989);
server->start();
std::this_thread::sleep_for(4s);
// destructor joins
}
这将为第一个连接的客户端提供 4 秒,并在所有连接完成后立即关闭。
我只是想用 acceptor socket 接受传入请求,当它进入 async_accept 时它抛出一个错误,我不确定是什么导致了错误。问题是我什至没有从客户端发送请求,但由于某种原因它仍然进入 async_accept 处理程序,这是导致错误
main.cpp
#include <iostream>
#include "server.hpp"
#include "connection.hpp"
class Connection;
int main(){
using Server_ = Server<Connection>;
auto server = std::make_unique<Server_>(8989);
server->start();
}
server.hpp
#pragma once
#include <thread>
#include <boost/asio.hpp>
template <typename Connection>
class Server{
using shared_connection = std::shared_ptr<Connection>;
private:
unsigned short port_;
std::thread io_thread_;
boost::asio::io_context ioc_;
boost::asio::io_context::work work_;
boost::asio::ip::tcp::endpoint endpoint_;
boost::asio::ip::tcp::acceptor acceptor_;
void handle_new_request(shared_connection connection, const system::error_code &ec){
if(!ec){
connection->start_operation();
}else{
error::print(ec);
return;
}
}
public:
explicit Server(unsigned short port)
: acceptor_(ioc_)
, work_(ioc_)
, port_(port)
, endpoint_(asio::ip::tcp::v4(), port) {
io_thread_ = std::move(std::thread([&]{ ioc_.run(); }));
io_thread_.join();
}
~Server() {
if(acceptor_.is_open())
acceptor_.close();
io_thread_.join();
}
void start(){
using namespace asio::ip;
system::error_code ec;
// creates an actual operating system socket
acceptor_.open(endpoint_.protocol(),ec);
acceptor_.set_option(tcp::acceptor::reuse_address(true),ec);
// binds to the endpoint
acceptor_.bind(endpoint_,ec);
if(!ec){
std::cout << "Listening for requests from port " << port_ << std::endl;
acceptor_.listen();
}else{
error::print(ec);
return;
}
shared_connection connection = std::make_shared<Connection>(ioc_);
acceptor_.async_accept(connection->sock_,[=](system::error_code ec){
handle_new_request(connection,ec);
});
}
};
connection.hpp
#pragma once
#include <memory>
#include <boost/asio.hpp>
class Connection : public std::enable_shared_from_this<Connection> {
using shared_connection = std::shared_ptr<Connection>;
std::vector<char> buffer_space_;
private:
boost::asio::mutable_buffers_1 buffer_;
boost::asio::io_context& ioc_;
public:
boost::asio::ip::tcp::socket sock_;
explicit Connection(boost::asio::io_context &context,const int &size = 1024)
: ioc_(context)
, sock_(context)
, buffer_space_(size)
, buffer_(buffer_space_.data(),size){}
~Connection(){ if(sock_.is_open()) sock_.close(); }
void start_operation(){
if(sock_.is_open()){
sock_.async_read_some(buffer_,[me = shared_from_this()](const system::error_code &ec, std::size_t bytes){
if(!ec){
for(int i=0;i<bytes;++i)
std::cout << me->buffer_space_[i];
std::cout << std::endl;
me->start_operation();
}else{
error::print(ec);
return;
}
});
}
}
};
error.hpp
#pragma once
#include <iostream>
#include <boost/system/error_code.hpp>
namespace error {
inline void print(const boost::system::error_code &ec){
std::cerr << "Error Code : " << ec.value() << ", Message : " << ec.message() << std::endl;
}
}
如有任何帮助,我们将不胜感激。谢谢!
错误在于析构函数中的 io_thread_.run()
会在那时销毁套接字对象
int main(){
using Server_ = Server<Connection>;
auto server = std::make_unique<Server_>(8989);
server->start();
}
server
将调用删除器,它在退出 main 时销毁 Server_
。您想在退出 main 之前加入任何线程或等待服务器关闭。
在你的情况下,你会加入 iothread,就像你尝试做的那样。
但是,您在服务器构造函数中执行此操作:
explicit Server(unsigned short port)
: acceptor_(ioc_)
, work_(ioc_)
, port_(port)
, endpoint_(asio::ip::tcp::v4(), port)
{
io_thread_ = std::move(std::thread([&] { ioc_.run(); }));
io_thread_.join();
}
I can't really figure out how this would not hang indefinitely due to the work_. On tangentially related observation is that
work_
is NOT initilaized beforeioc_
(orthread_
) because initialization happens in order of member declaration instead of order in which the initializers appear. You will want to fix the declaration order regardless:boost::asio::io_context ioc_; boost::asio::ip::tcp::acceptor acceptor_; boost::asio::io_context::work work_; unsigned short port_; boost::asio::ip::tcp::endpoint endpoint_; std::thread io_thread_;
Similarly in
Connection
:private: boost::asio::io_context& ioc_; public: boost::asio::ip::tcp::socket sock_; private: std::vector<char> buffer_space_; boost::asio::mutable_buffers_1 buffer_;
固定演示
#include <iostream>
#include <boost/system/error_code.hpp>
namespace error {
inline void print(const boost::system::error_code& ec)
{
std::cerr << "Error Code : " << ec.value()
<< ", Message : " << ec.message() << std::endl;
}
}
#include <memory>
#include <boost/asio.hpp>
class Connection : public std::enable_shared_from_this<Connection> {
using shared_connection = std::shared_ptr<Connection>;
private:
boost::asio::io_context& ioc_;
public:
boost::asio::ip::tcp::socket sock_;
private:
std::vector<char> buffer_space_;
boost::asio::mutable_buffers_1 buffer_;
public:
explicit Connection(
boost::asio::io_context& context, const int& size = 1024)
: ioc_(context)
, sock_(context)
, buffer_space_(size)
, buffer_(buffer_space_.data(), size)
{
}
void start_operation()
{
if (sock_.is_open()) {
sock_.async_read_some(buffer_,
[me = shared_from_this()](
const boost::system::error_code& ec, std::size_t bytes) {
if (!ec) {
for (size_t i = 0; i < bytes; ++i) {
std::cout << me->buffer_space_[i];
}
std::cout << std::endl;
me->start_operation();
} else {
error::print(ec);
return;
}
});
}
}
};
#include <thread>
#include <boost/asio.hpp>
template <typename Connection> class Server {
using shared_connection = std::shared_ptr<Connection>;
private:
boost::asio::io_context ioc_;
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>
work_ {ioc_.get_executor()};
uint16_t port_;
boost::asio::ip::tcp::endpoint endpoint_;
std::thread io_thread_;
void handle_new_request(
shared_connection connection, const boost::system::error_code& ec)
{
if (!ec) {
connection->start_operation();
} else {
error::print(ec);
return;
}
}
public:
explicit Server(uint16_t port)
: acceptor_(ioc_)
, port_(port)
, endpoint_(boost::asio::ip::tcp::v4(), port)
, io_thread_([&] { ioc_.run(); })
{ ; }
~Server()
{
if (acceptor_.is_open()) {
boost::system::error_code ec;
acceptor_.cancel(ec);
//acceptor_.close(ec);
}
work_.reset();
io_thread_.join();
}
void start()
{
using boost::asio::ip::tcp;
boost::system::error_code ec;
// creates an actual operating system socket
acceptor_.open(endpoint_.protocol(), ec);
acceptor_.set_option(tcp::acceptor::reuse_address(true), ec);
// binds to the endpoint
acceptor_.bind(endpoint_, ec);
if (!ec) {
std::cout << "Listening for requests from port " << port_
<< std::endl;
acceptor_.listen();
} else {
error::print(ec);
return;
}
shared_connection connection = std::make_shared<Connection>(ioc_);
acceptor_.async_accept(
connection->sock_, [=, this](boost::system::error_code ec) {
handle_new_request(connection, ec);
});
}
};
#include <iostream>
//#include "server.hpp"
//#include "connection.hpp"
using namespace std::chrono_literals;
class Connection;
int main()
{
using Server_ = Server<Connection>;
auto server = std::make_unique<Server_>(8989);
server->start();
std::this_thread::sleep_for(4s);
// destructor joins
}
这将为第一个连接的客户端提供 4 秒,并在所有连接完成后立即关闭。