Suppose I have a socket:
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)) );
And I store a weak_ptr to the said socket in a container. I need this because I want to allow clients to request for a list of other clients, so they can send messages to each other.
clients_.insert(socket); // pseudocode
Then I run some async operations
socket->async_receive( boost::asio::buffer(&(*header), sizeof(Header))
, 0
, std::bind(handleReceiveHeader, this, std::placeholders::_1, std::placeholders::_2, header, socket));
How do I detect when the connection is closed so I can remove my socket from the container?
clients_.erase(socket); // pseudocode
A TCP socket disconnect is usually signalled in asio
by an eof
or a connection_reset
. E.g.
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
}
}
I use boost::signals2
to signal the disconnect although you can always pass a pointer to a function to your socket class and then call that.
Be careful about your socket and callback lifetimes, see: boost-async-functions-and-shared-ptrs
There are many options, some of them are:
As you store weak_ptr
in container - it will not prolong lifetime of socket, so when your handler will get boost::asio::error::eof
(or whatever), it will not do copy/move of shared_ptr
, and socket will be deleted (if you don't have any others shared_ptr
s to it). So, you can do something like: if(socket.expired()) clients_.erase(socket);
Check error code in your handler - it will indicate when connection is closed. Using this info - you can call clients_.erase
from handler itself.
Could you give an example of #2?
It will be something like:
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
}
}
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With