boost websocket and io_context reusability for reestablishability of a connection

968 views Asked by At

I have writted a small websocket client using boost::beast::websocket and boost::asio::io_context in C++. I am having a state machine with following states:

enum class State {
    GDR_PROVISING,
    WEBSOCKET_HANDSHAKE,
    REGISTRATION,
    READY,
    CLEANUP,
};

If the code is unable to set-up a connection or fails after a connection is established (possible reasons: Internet is down, Service is down, Server sends a close frame), then the state machine moves towards CLEANUP state and should do the cleanup.

I am not sure if I can reuse the same io_context and websocket::stream. Currently, my io_context is only used in this single thread. I am planning to use pointers of websockets and io_context and delete them in CLEANUP and allocate them again in GDR_PROVISING.

Can I use same websocket and io_context instance for reestablishing the connecction to the server? May be I need to call some member functions like stop or reset?

My READY looks like this now:

    case State::READY:
    {
        // TODO: Send the Message from the vector
        {
            std::lock_guard<std::mutex> msgGaurd(msgMutex_);
            for (const auto& m: sendMsgQueue_) {
                boost::system::error_code ec;
                pWebStream_->write(boost::asio::buffer(m.toString()), ec);
            }
        }
        // Call io_context run_until to process read messages async because there is no way for non-blocking read in boost for websockets!
        pIoc_->run_until(std::chrono::steady_clock::now() + /* TODO: Add some time_point */);
        break;
    }

    case State::CLEANUP:
    {
        // TODO: Verify if we should delete the stream!
        if (pWebStream_)
            delete pWebStream_;
        if (pIoc_)
            delete pIoc_;
        pWebStream_ = nullptr;
        pIoc_ = nullptr;
        state_ = State::GDR_PROVISING;
        break;
    }
1

There are 1 answers

0
user233009 On

You can reuse io_context as normal. The call to run wont terminate unless there is no more work left to do when it tries to do another event loop iteration.

You also can reuse the socket using get_lowest_layer(*pWebStream_).close(), reopening it with get_lowest_layer(*pWebStream_).open(), and calling async_connect as normal. But, I think your code would be cleaner by completely resetting the object like you do.

If you do want to reset the socket, I highly recommend you try using std::optional. It makes no heap allocations, and you don't have to worry about leaking memory.