c – boost :: asio – 知道何时必须关闭/关闭连接

我实现了一个协议(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.

点赞