Boost asio 获取“错误代码:125 操作已取消”[关闭]
Posted
技术标签:
【中文标题】Boost asio 获取“错误代码:125 操作已取消”[关闭]【英文标题】:Boost asio getting `Error Code : 125 Operation cancelled` [closed] 【发布时间】:2021-02-09 06:15:44 【问题描述】:我只是试图用 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();
服务器.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);
);
;
连接.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;
);
;
错误.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()
,这会破坏套接字对象
【问题讨论】:
请提供minimal reproducible example 猜测接受器正在关闭,这会导致挂起的async_accept
被取消
@AlanBirtles 是的,我已经进行了必要的更改。如果接收器正在关闭,则意味着拥有它的服务器对象正在被销毁我认为不是这种情况,因为服务器对象的析构函数具有 io_thread_.join()
@Bad_Panda 您的服务器实例在 main() 退出时被销毁。无需通过您的代码,这将取消所有未完成的操作,然后可以从析构函数中加入线程。
@janm 是的,我刚刚意识到,非常感谢您的帮助!
【参考方案1】:
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();
我真的不知道这怎么不会因为工作而无限期挂起_。与切线相关的观察是
work_
没有在ioc_
(或thread_
)之前初始化,因为初始化是按照成员声明的顺序而不是初始化程序出现的顺序发生的。无论如何,您都需要修正申报顺序: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_;
同样在
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_;
固定演示
Live On Coliru
#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 秒的时间,并在所有连接完成后立即关闭。
【讨论】:
以上是关于Boost asio 获取“错误代码:125 操作已取消”[关闭]的主要内容,如果未能解决你的问题,请参考以下文章
如何使用boost asio stable timer expiry获取执行时间点