C++ UDP Server io_context running in thread exits before work can start

  boost-asio, c++, udp

I’m new to C++ but so far most of the asio stuff has made sense. I am however stuggling to get my UDPServer working.

My question is possibly similar to: Trying to write UDP server class, io_context doesn't block

I think my UDPServer stops before work can be given to its io_context. However, I am issuing work to the context before calling io_context.run() so I don’t understand why.

Of course, I am not entirely sure if I am even on the right track with the above statement and would appreciate some guidance. Here is my class:

template<typename message_T>
    class UDPServer
    {
    public:
        UDPServer(uint16_t port)
            : m_socket(m_asioContext, asio::ip::udp::endpoint(asio::ip::udp::v4(), port))
        {
            m_port = port;
        }

        virtual ~UDPServer()
        {
            Stop();
        }



    public:

        // Starts the server!
        bool Start()
        {
            try
            {
                // Issue a task to the asio context
                WaitForMessages();

                m_threadContext = std::thread([this]() { m_asioContext.run(); });
            }
            catch (std::exception& e)
            {
                // Something prohibited the server from listening
                std::cerr << "[SERVER @ PORT " << m_port << "] Exception: " << e.what() << "n";
                return false;
            }

            std::cout << "[SERVER @ PORT " << m_port << "] Started!n";
            return true;
        }

        // Stops the server!
        void Stop()
        {
            // Request the context to close
            m_asioContext.stop();

            // Tidy up the context thread
            if (m_threadContext.joinable()) m_threadContext.join();

            // Inform someone, anybody, if they care...
            std::cout << "[SERVER @ PORT " << m_port << "] Stopped!n";
        }


        void WaitForMessages()
        {

            m_socket.async_receive_from(asio::buffer(vBuffer.data(), vBuffer.size()), m_endpoint,
                [this](std::error_code ec, std::size_t length)
                {
                    if (!ec)
                    {
                        
                        std::cout << "[SERVER @ PORT " << m_port << "] Got " << length << " bytes n Data: " << vBuffer.data() << "n" << "Address: " << m_endpoint.address() << " Port: " << m_endpoint.port() << "n" << "Data: " << m_endpoint.data() << "n";

                    }
                    else
                    {
                        std::cerr << "[SERVER @ PORT " << m_port << "] Exception: " << ec.message() << "n";
                        return;
                    }

                    WaitForMessages();
                }
            );
        }

        void Send(message_T& msg, const asio::ip::udp::endpoint& ep)
        {
            asio::post(m_asioContext,
                [this, msg, ep]()
                {
                    // If the queue has a message in it, then we must
                    // assume that it is in the process of asynchronously being written.
                    
                    bool bWritingMessage = !m_messagesOut.empty();
                    m_messagesOut.push_back(msg);
                    if (!bWritingMessage)
                    {
                        WriteMessage(ep);
                    }
                }
            );
        }

    private:

        void WriteMessage(const asio::ip::udp::endpoint& ep)
        {

            m_socket.async_send_to(asio::buffer(&m_messagesOut.front(), sizeof(message_T)), ep,
                [this, ep](std::error_code ec, std::size_t length)
                {

                    if (!ec)
                    {

                        m_messagesOut.pop_front();

                        // If the queue is not empty, there are more messages to send, so
                        // make this happen by issuing the task to send the next header.
                        if (!m_messagesOut.empty())
                        {
                            WriteMessage(ep);
                        }
                        
                    }
                    else
                    {
                        std::cout << "[SERVER @ PORT " << m_port << "] Write Header Fail.n";
                        m_socket.close();
                    }
                });
        }

        void ReadMessage()
        {
        }

    private:
        
        uint16_t m_port = 0;
        asio::ip::udp::endpoint m_endpoint;
        std::vector<char> vBuffer = std::vector<char>(21);


    protected:
        TSQueue<message_T> m_messagesIn;
        TSQueue<message_T> m_messagesOut;
        Message<message_T> m_tempMessageBuf;
        asio::io_context m_asioContext;
        std::thread m_threadContext;
        asio::ip::udp::socket m_socket;
    };
}

Source: Windows Questions C++

LEAVE A COMMENT