...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
The WebSocket Protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host that has opted-in to communications from that code. The protocol consists of an opening handshake followed by basic message framing, layered over TCP. The goal of this technology is to provide a mechanism for browser-based applications needing two-way communication with servers without relying on opening multiple HTTP connections.
Beast provides developers with a robust WebSocket implementation built on Boost.Asio with a consistent asynchronous model using a modern C++ approach.
Note | |
---|---|
This documentation assumes familiarity with Boost.Asio and the protocol specification described in rfc6455. Sample code and identifiers appearing in this section is written as if these declarations are in effect: #include <boost/beast.hpp> #include <boost/asio.hpp> #include <boost/asio/ssl.hpp>
namespace net = boost::asio; namespace beast = boost::beast; using namespace boost::beast; using namespace boost::beast::websocket; net::io_context ioc; tcp_stream sock(ioc); net::ssl::context ctx(net::ssl::context::tlsv12); |
A WebSocket connection requires a stateful object, represented in Beast by
a single class template websocket::stream
. The interface uses the layered
stream model. A websocket stream object contains another stream object, called
the "next layer", which it uses to perform I/O. Descriptions of each
template parameter follow:
namespace boost { namespace beast { namespace websocket { template< class NextLayer, bool deflateSupported = true> class stream; } // websocket } // beast } // boost
Table 1.30. WebSocket Stream Template Parameters
Name |
Description |
---|---|
|
The type of the next layer. An object of this type will be constructed and maintained for the lifetime of the stream. All reads and writes will go through the next layer. This type must meet the requirements of either SyncStream, AsyncStream, or both, depending on the style of I/O that is to be performed. |
|
When this value is
When the value is |
When a stream is constructed, any arguments provided to the constructor are forwarded to the next layer object's constructor. This declares a stream over a plain TCP/IP socket using an I/O context:
// This newly constructed WebSocket stream will use the specified // I/O context and have support for the permessage-deflate extension. stream<tcp_stream> ws(ioc);
Tip | |
---|---|
Websocket streams use their own protocol-specific timeout feature. When using
a websocket stream with the |
As with most I/O objects, a websocket stream is not thread-safe.
Undefined behavior results if two different threads access the object concurrently.
For multi-threaded programs, the tcp_stream
can be constructed from an executor, in this case a strand. The stream declared
below will use a strand to invoke all completion handlers:
// The `tcp_stream` will be constructed with a new // strand which uses the specified I/O context. stream<tcp_stream> ws(net::make_strand(ioc));
If the next layer supports move-construction, then the websocket stream can be constructed from a moved-from object.
// Ownership of the `tcp_stream` is transferred to the websocket stream stream<tcp_stream> ws(std::move(sock));
The next layer may be accessed by calling stream::next_layer
.
// Calls `close` on the underlying `beast::tcp_stream` ws.next_layer().close();
To use WebSockets over SSL, use an instance of the net::ssl::stream
class template as the template type for the stream. The required net::io_context
and net::ssl::context
arguments are forwarded to the wrapped stream's constructor:
// The WebSocket stream will use SSL and a new strand stream<net::ssl::stream<tcp_stream>> wss(net::make_strand(ioc), ctx);
Important | |
---|---|
Code which declares websocket stream objects using Asio SSL types must include
the file |
As before, the underlying SSL stream may be accessed by calling next_layer
.
// Perform the SSL handshake in the client role wss.next_layer().handshake(net::ssl::stream_base::client);
With multi-layered streams such as the one declared above, accessing an individual
layer can be cumbersome when using chained calls to next_layer
.
The function get_lowest_layer
returns the last
stream in a stack of layers in a layered stream. Here we access the lowest
layer to cancel all outstanding I/O.
// Cancel all pending I/O on the underlying `tcp_stream` get_lowest_layer(wss).cancel();
Please note that websocket streams do not support non-blocking modes.