私がソケットを持っているとしましょう:
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
TCPソケットの切断は、通常、asio
またはconnection_reset
によってeof
で通知されます。
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
多くのオプションがあり、そのうちのいくつかは次のとおりです。
_weak_ptr
_をコンテナーに格納すると、ソケットの寿命が延びることはないため、ハンドラーが_boost::asio::error::eof
_(またはその他)を取得しても、_shared_ptr
_のコピー/移動は行われません。ソケットは削除されます(他に_shared_ptr
_ sがない場合)。したがって、次のようなことができます:if(socket.expired()) clients_.erase(socket);
ハンドラーのエラーコードを確認してください-接続が閉じられたときに表示されます。この情報を使用すると、ハンドラー自体から_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
}
}
);
_