Search code examples
c++boostwebsocketbeast

boost beast websocket connection close handler


I am new to boost and i am trying to write a simple chat application for websocket. For reference i'm using the websocket-server-sync example from the website.

I made a global vector that stores websocket::streams, and in the do_session method after creating the websocket i push it in the vector.

std::vector<websocket::stream<tcp::socket>*> socket_streams;

Everytime i read a message i send it to everyone from this vector, so its working well so far. However when someone closes the connection (even when its not properly closed, e.g. the internet connection goes down) i want to remove the stream object from my vector. I tried to look in the beast headers for a "close handler" or something like that, but i couldn't find anything. Is there a way to do this? Like:

void close_handler(websocket::stream<tcp::socket>* _stream) 
{
   //remove _stream from socket_streams
}

Solution

  • From what I understand, your problem is to extend the lifetime of the stream outside the try/catch clause.

    Keeping the assumption that the constructor can throw, you can use the copy constructor inside the try :

    void do_session(tcp::socket& socket)
    {
        websocket::stream<tcp::socket> ws;
        try
        {
            ws = std::move(websocket::stream<tcp::socket>>(std::move(socket)));
            add_socket(&ws);
            // ....
        }
        catch(boost::system::system_error const& se) { ... }
        catch(std::exception const& e) {}
    
        erase_socket_if_exists(&ws);
    }
    

    If the move-assignment hadn't existed, you could have used std::uniq_ptr<>.

    Note that you cannot avoid the race condition of trying to write to a close stream. That's why you have to handle the case where a write throws an exception.

    Also note that with you scheme, you must hold the lock of the container until you have finished writing to all sockets.