Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does boost::asio support websockets?

I posted a question earlier asking why does my server (written in C++ and boost::asio) can't connect with a client (written in Javascript). Is the problem that the Javascript Websockets are different than boost::asio sockets ? Does boost::asio not support websockets ? What is the easiest way to work this out ?

like image 892
dimitris93 Avatar asked Apr 11 '16 23:04

dimitris93


People also ask

Can you proxy WebSockets?

WebSocket communication can take successfully take place in the presence of forward proxies, providing the client and proxy server have been configured properly to deal with it. This page explains how to configure a Universal Messaging JavaScript client and Apache serving as a forward proxy to permit WebSocket use.

Is WebSockets obsolete?

Websockets are largely obsolete because nowadays, if you create a HTTP/2 fetch request, any existing keepalive connection to that server is used, so the overhead that pre-HTTP/2 XHR connections needed is lost and with it the advantage of Websockets.

What will replace WebSockets?

WebTransport is a new specification offering an alternative to WebSockets. For applications that need low-latency, event-driven communication between endpoints, WebSockets has been the go-to choice, but WebTransport may change that.

Does load balancer support WebSockets?

Azure Load balancer does not support WebSockets. You can consider using Application Gateway as it natively supports WebSockets.


1 Answers

Boost.Beast, now part of Boost, is built on top of Boost.Asio and works the way you expect. It comes with example code and documentation. Check it out here: www.boost.org/libs/beast

Here's a complete program that sends a message to the echo server:

#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <cstdlib>
#include <iostream>
#include <string>

namespace beast = boost::beast;         // from <boost/beast.hpp>
namespace http = beast::http;           // from <boost/beast/http.hpp>
namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
namespace net = boost::asio;            // from <boost/asio.hpp>
using tcp = boost::asio::ip::tcp;       // from <boost/asio/ip/tcp.hpp>

// Sends a WebSocket message and prints the response
int main(int argc, char** argv)
{
    try
    {
        // Check command line arguments.
        if(argc != 4)
        {
            std::cerr <<
                "Usage: websocket-client-sync <host> <port> <text>\n" <<
                "Example:\n" <<
                "    websocket-client-sync echo.websocket.org 80 \"Hello, world!\"\n";
            return EXIT_FAILURE;
        }
        std::string host = argv[1];
        auto const  port = argv[2];
        auto const  text = argv[3];

        // The io_context is required for all I/O
        net::io_context ioc;

        // These objects perform our I/O
        tcp::resolver resolver{ioc};
        websocket::stream<tcp::socket> ws{ioc};

        // Look up the domain name
        auto const results = resolver.resolve(host, port);

        // Make the connection on the IP address we get from a lookup
        auto ep = net::connect(ws.next_layer(), results);

        // Update the host_ string. This will provide the value of the
        // Host HTTP header during the WebSocket handshake.
        // See https://tools.ietf.org/html/rfc7230#section-5.4
        host += ':' + std::to_string(ep.port());

        // Set a decorator to change the User-Agent of the handshake
        ws.set_option(websocket::stream_base::decorator(
            [](websocket::request_type& req)
            {
                req.set(http::field::user_agent,
                    std::string(BOOST_BEAST_VERSION_STRING) +
                        " websocket-client-coro");
            }));

        // Perform the websocket handshake
        ws.handshake(host, "/");

        // Send the message
        ws.write(net::buffer(std::string(text)));

        // This buffer will hold the incoming message
        beast::flat_buffer buffer;

        // Read a message into our buffer
        ws.read(buffer);

        // Close the WebSocket connection
        ws.close(websocket::close_code::normal);

        // If we get here then the connection is closed gracefully

        // The make_printable() function helps print a ConstBufferSequence
        std::cout << beast::make_printable(buffer.data()) << std::endl;
    }
    catch(std::exception const& e)
    {
        std::cerr << "Error: " << e.what() << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}
like image 167
Vinnie Falco Avatar answered Oct 11 '22 13:10

Vinnie Falco