我实现了一个协议(socks),它要求我的服务器中继从客户端到目的地的连接.
我实现中继部分的方法是使用这样的东西:
socket_.async_read_some(boost::asio::buffer(dataClient_, 1024),
boost::bind(&ProxySocksSession::HandleClientProxyRead, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
remoteSock_.async_read_some(boost::asio::buffer(dataRemote_, 1024),
boost::bind(&ProxySocksSession::HandleRemoteProxyRead, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
当然还有更多的代码 – 那里的处理程序中继来自socket_的数据并将其发送到remoteSock_,反之亦然(来自remoteSock_的所有数据都被转发到
插座_)
我看到异步tcp服务器回显示例(http://www.boost.org/doc/libs/1_38_0/doc/html/boost_asio/example/echo/async_tcp_echo_server.cpp),并且在何时关闭连接的逻辑只是删除连接对象 – 删除此 – (它关闭了它拥有的通信套接字)当boost :: system :: error_code是收到处理程序.
我怎么自己应该处理这个案子?这次我有2个套接字的数据,如果我没有干净地关闭,我可能会在所有数据传输之前关闭(例如来自客户端的套接字 – socket_ – 可能关闭连接但是 – remoteSock – 可能仍然试图发送数据).
编辑我已经更新了我的代码,如果我检测到其中一个套接字(remoteSock_或socket_)读/写处理程序报告了一个boost :: system :: error_code我执行以下操作以关闭通信:
void ProxySocksSession::Shutdown()
{
if (!shutdownInProgress_)
{
std::cout << "Shuting down ..." << std::endl;
shutdownInProgress_ = true;
remoteSock_.shutdown((boost::asio::ip::tcp::socket::shutdown_both));
remoteSock_.close();
socket_.shutdown((boost::asio::ip::tcp::socket::shutdown_both));
socket_.close();
parentConnection_.Shutdown();
}
}
问题是即使我在套接字上调用shutdown()和close(),我仍然会收到对套接字处理程序的调用(这些是在同一个类中,ProxySocksSession).到这些时,我的ProxySocksSession实例已被删除(删除由上面的parentConnection_.Shutdown()完成)
最佳答案 我设法提出了一个有效的解决方案(不会导致所描述的问题).
我还包括下面的处理函数的骨架,以便看到这个想法:
void ProxySocksSession::Start()
{
socket_.async_read_some(boost::asio::buffer(dataClient_, 1024),
boost::bind(&ProxySocksSession::HandleClientProxyRead, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
remoteSock_.async_read_some(boost::asio::buffer(dataRemote_, 1024),
boost::bind(&ProxySocksSession::HandleRemoteProxyRead, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
// received data from socks5 client - completion handler
void ProxySocksSession::HandleClientProxyRead(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error && !this->shutdownInProgress_)
{
// relay data coming from client to remote endpoint -> async write to remoteSock_
// async read some more data from socket_
}
else
{
Shutdown();
}
}
//received data from socks5 remote endpoint (socks5 client destination)
void ProxySocksSession::HandleRemoteProxyRead(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error && !this->shutdownInProgress_)
{
// relay data coming from remote endpoint to client -> async write to socket__
// async read some more data from remoteSock_
}
else
{
Shutdown();
}
}
void ProxySocksSession::Shutdown()
{
if (!shutdownInProgress_)
{
std::cout << "Shuting down ..." << std::endl;
shutdownInProgress_ = true;
//remoteSock_.close(); -- no need as it is closed automatically as part of parentConnection_ shutdown/deletion
//socket_.close(); -- no need as it is closed automatically as part of parentConnection_ shutdown/deletion
parentConnection_.Shutdown();
}
}
这里的关键是我在处理绑定完成处理程序时使用了shared_from_this()这一事实.这样,我确保在套接字关闭时调用所有ProxySocksSession处理程序之前,parentConnection_实例不会删除ProxySocksSession实例,而该实例具有到ProxySocksSession的shared_ptr.