14

ソケットがあるとします:

std::shared_ptr<tcp::socket> socket( new tcp::socket(acceptor.get_io_service()) );
acceptor.async_accept( *socket, std::bind( handleAccept, this, std::placeholders::_1, socket, std::ref(acceptor)) );

そして、コンテナ内の上記ソケットにweak_ptrを格納します。クライアントが他のクライアントのリストを要求できるようにして、相互にメッセージを送信できるようにするために、これが必要です。

clients_.insert(socket);  // pseudocode

次に、いくつかの非同期操作を実行します

socket->async_receive( boost::asio::buffer(&(*header), sizeof(Header))
    , 0
    , std::bind(handleReceiveHeader, this, std::placeholders::_1, std::placeholders::_2, header, socket));

コンテナーからソケットを削除できるように、接続が閉じられたことを検出するにはどうすればよいですか?

clients_.erase(socket); // pseudocode
4

2 に答える 2

23

通常、TCP ソケットの切断は、またはasioによって通知されます。例えばeofconnection_reset

  void async_receive(boost::system::error_code const& error,
                     size_t bytes_transferred)
  {
    if ((boost::asio::error::eof == error) ||
        (boost::asio::error::connection_reset == error))
    {
      // handle the disconnect.
    }
    else
    {
       // read the data 
    }
  }

boost::signals2関数へのポインターをソケットクラスにいつでも渡してから呼び出すことができますが、私は切断を通知するために使用します。

ソケットとコールバックの有効期間に注意してください。boost-async-functions-and-shared-ptrs を参照してください。

于 2013-11-10T16:17:01.557 に答える
1

多くのオプションがあり、そのうちのいくつかは次のとおりです。

  1. コンテナに保存weak_ptrすると、ソケットの有効期間が延長されないため、ハンドラーが取得するときboost::asio::error::eof(または何でも)、のコピー/移動は行われず、ソケットは削除されます(他に sshared_ptrがない場合)shared_ptrそれ)。したがって、次のようなことができます。if(socket.expired()) clients_.erase(socket);

  2. ハンドラーのエラー コードを確認してください。接続が閉じられたときに示されます。この情報を使用してclients_.erase、ハンドラー自体から呼び出すことができます。

#2の例を挙げていただけますか?

次のようになります。

socket->async_receive
(
    boost::asio::buffer(&(*header), sizeof(Header)), 0,
    [=, &clients_](const system::error_code& error, size_t bytes_transferred)
    {
        if(error) // or some specific code
        {
            clients_.erase(socket); // pseudocode
        }
        else
        {
            // continue, launch new operation, etc
        }
    }
);
于 2013-11-10T08:26:18.343 に答える