如何正确关闭asio-tcp服务器
How to properly shutdown asio tcp server?
关闭异步boost asio-tcp服务器的正确方法是什么?我目前的解决方案通常在析构函数中死锁。为什么?
class connection;
typedef std::set<shared_ptr<connection>> connection_set;
class connection : public enable_shared_from_this<connection>
{
shared_ptr<tcp::socket> socket_;
std::array<char, 8192> data_;
shared_ptr<connection_set> connection_set_;
public:
static shared_ptr<connection> create(shared_ptr<tcp::socket> socket, shared_ptr<connection_set> connection_set)
{
auto con = shared_ptr<connection>(new connection(std::move(socket), std::move(connection_set)));
con->read_some();
return con;
}
void on_next(const event& e)
{
// async_write_some ...
}
private:
connection(shared_ptr<tcp::socket> socket, shared_ptr<connection_set> connection_set)
: socket_(std::move(socket))
, connection_set_(std::move(connection_set))
{
}
void handle_read(const boost::system::error_code& error, size_t bytes_transferred)
{
if(!error)
{
on_read(std::string(data_.begin(), data_.begin() + bytes_transferred));
read_some();
}
else if (error != boost::asio::error::operation_aborted)
connection_set_->erase(shared_from_this());
else
read_some();
}
void handle_write(const shared_ptr<std::vector<char>>& data, const boost::system::error_code& error, size_t bytes_transferred)
{
if(!error)
{
}
else if (error != boost::asio::error::operation_aborted)
connection_set_->erase(shared_from_this());
}
void read_some()
{
socket_->async_read_some(boost::asio::buffer(data_.data(), data_.size()), std::bind(&connection::handle_read, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
}
void on_read(std::string str)
{
// parse the string...
}
};
class tcp_observer
{
boost::asio::io_service service_;
tcp::acceptor acceptor_;
std::shared_ptr<connection_set> connection_set_;
boost::thread thread_;
public:
tcp_observer(unsigned short port)
: acceptor_(service_, tcp::endpoint(tcp::v4(), port))
, thread_(std::bind(&boost::asio::io_service::run, &service_))
{
start_accept();
}
~tcp_observer()
{
// Deadlocks...
service_.post([=]
{
acceptor_.close();
connection_set_->clear();
});
thread_.join();
}
void on_next(const event& e)
{
service_.post([=]
{
BOOST_FOREACH(auto& connection, *connection_set_)
connection->on_next(e);
});
}
private:
void start_accept()
{
auto socket = std::make_shared<tcp::socket>(service_);
acceptor_.async_accept(*socket, std::bind(&tcp_observer::handle_accept, this, socket, std::placeholders::_1));
}
void handle_accept(const shared_ptr<tcp::socket>& socket, const boost::system::error_code& error)
{
if (!acceptor_.is_open())
return;
if (!error)
connection_set_->insert(connection::create(socket, connection_set_));
start_accept();
}
};
这种"死锁"是因为连接不会被破坏,因为传递shared_from_this()
的操作仍有挂起的操作。
调用每个连接的套接字关机(..)和关闭(..)。然后等待完成,这表示eof或operation_aborted。
相关文章:
- 提升 Asio TCP 服务器 处理多个客户端
- TCP 服务器的异步读取使用 boost::asio 打印客户端套接字发送的数据
- 提升 ASIO TCP 服务器架构
- 使用线程池提升 ASIO 多线程 TCP 服务器
- 使用Valgrind时,偶尔的BOOST :: ASIO TCP服务器故障在Localhost上运行
- Boost asio,单个TCP服务器,多个客户端
- 如何通过 boost asio 支持 TCP 服务器中的多个连接
- 使用Boost.ASIO与服务器进行简单的网络tcp通信
- BOOST :: ASIO TCP数据库服务器
- 提升ASIO TCP,为什么我不能在服务器端只有一个数据套接字可以打开和关闭
- 提升 ASIO TCP 服务器
- 如何防止c++asio tcp服务器关闭
- Boost::asio - 如何中断被阻止的 TCP 服务器线程
- TCP 服务器 w/ boost::asio,线程池与无堆栈协程的可扩展性
- 调用 boost::asio::tcp::socket 方法后async_read处理程序在服务器中返回错误
- 如何正确关闭asio-tcp服务器
- Boost::asio TCP服务器——从客户端读取消息
- Boost::asio阻塞Tcp服务器混淆
- 当我的 Boost::asio tcp 服务器刚刚开始运行时,如何启动"event"(又名 io_service.run() )?
- boost asio TCP 服务器必须绑定到 IP 地址