5
什麼是關閉異步升壓asio tcp服務器的正確方法?我目前的解決方案通常在析構函數中死鎖。爲什麼?如何正確關閉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();
}
};
我可以調用套接字關閉並關閉另一個線程?或者它是否必須在io_service線程中? – ronag 2012-02-09 09:48:46
根據[tcp socket文檔](http://www.boost.org/doc/libs/1_48_0/doc/html/boost_asio/reference/ip__tcp/socket.html),訪問必須同步(或每次訪問由同一個線程)。 – Simon 2012-02-09 11:15:24