forked from boostorg/beast
117 lines
4.9 KiB
Plaintext
117 lines
4.9 KiB
Plaintext
|
|
[/
|
||
|
|
Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||
|
|
|
||
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||
|
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||
|
|
]
|
||
|
|
|
||
|
|
[section:control Control Frames]
|
||
|
|
|
||
|
|
Control frames are small (less than 128 bytes) messages entirely contained
|
||
|
|
in an individual WebSocket frame. They may be sent at any time by either
|
||
|
|
peer on an established connection, and can appear in between continuation
|
||
|
|
frames for a message. There are three types of control frames: ping, pong,
|
||
|
|
and close.
|
||
|
|
|
||
|
|
A sent ping indicates a request that the sender wants to receive a pong. A
|
||
|
|
pong is a response to a ping. Pongs may be sent unsolicited, at any time.
|
||
|
|
One use for an unsolicited pong is to inform the remote peer that the
|
||
|
|
session is still active after a long period of inactivity. A close frame
|
||
|
|
indicates that the remote peer wishes to close the WebSocket connection.
|
||
|
|
The connection is considered gracefully closed when each side has sent
|
||
|
|
and received a close frame.
|
||
|
|
|
||
|
|
During read operations, Beast automatically reads and processes control
|
||
|
|
frames. Pings are replied to as soon as possible with a pong, received
|
||
|
|
ping and pongs are delivered to the ping callback. The receipt of a close
|
||
|
|
frame initiates the WebSocket close procedure, eventually resulting in the
|
||
|
|
error code [link beast.ref.websocket__error `error::closed`] being delivered
|
||
|
|
to the caller in a subsequent read operation, assuming no other error
|
||
|
|
takes place.
|
||
|
|
|
||
|
|
A consequence of this automatic behavior is that caller-initiated read
|
||
|
|
operations can cause socket writes. However, these writes will not
|
||
|
|
compete with caller-initiated write operations. For the purposes of
|
||
|
|
correctness with respect to the stream invariants, caller-initiated
|
||
|
|
read operations still only count as a read. This means that callers can
|
||
|
|
have a simultaneously active read, write, and ping operation in progress,
|
||
|
|
while the implementation also automatically handles control frames.
|
||
|
|
|
||
|
|
[heading Ping and Pong Frames]
|
||
|
|
|
||
|
|
Ping and pong messages are control frames which may be sent at any time
|
||
|
|
by either peer on an established WebSocket connection. They are sent
|
||
|
|
using the functions
|
||
|
|
[link beast.ref.websocket__stream.ping `ping`] and
|
||
|
|
[link beast.ref.websocket__stream.pong `pong`].
|
||
|
|
|
||
|
|
To be notified of ping and pong control frames, callers may register a
|
||
|
|
"ping callback" using [link beast.ref.websocket__stream.set_option `set_option`].
|
||
|
|
The object provided with this option should be callable with the following
|
||
|
|
signature:
|
||
|
|
```
|
||
|
|
void on_ping(bool is_pong, websocket::ping_data const& payload);
|
||
|
|
...
|
||
|
|
ws.set_option(ping_callback{&on_ping});
|
||
|
|
```
|
||
|
|
|
||
|
|
When a ping callback is registered, all pings and pongs received through
|
||
|
|
either synchronous read functions or asynchronous read functions will
|
||
|
|
invoke the ping callback, with the value of `is_pong` set to `true` if a
|
||
|
|
pong was received else `false` if a ping was received. The payload of
|
||
|
|
the ping or pong control frame is passed in the payload argument.
|
||
|
|
|
||
|
|
Unlike regular completion handlers used in calls to asynchronous initiation
|
||
|
|
functions, the ping callback only needs to be set once. The callback is not
|
||
|
|
reset when a ping or pong is received. The same callback is used for both
|
||
|
|
synchronous and asynchronous reads. The ping callback is passive; in order
|
||
|
|
to receive pings and pongs, a synchronous or asynchronous stream read
|
||
|
|
function must be active.
|
||
|
|
|
||
|
|
[note
|
||
|
|
When an asynchronous read function receives a ping or pong, the
|
||
|
|
ping callback is invoked in the same manner as that used to invoke
|
||
|
|
the final completion handler of the corresponding read function.
|
||
|
|
]
|
||
|
|
|
||
|
|
[heading Close Frames]
|
||
|
|
|
||
|
|
The WebSocket protocol defines a procedure and control message for initiating
|
||
|
|
a close of the session. Handling of close initiated by the remote end of the
|
||
|
|
connection is performed automatically. To manually initiate a close, use
|
||
|
|
the
|
||
|
|
[link beast.ref.websocket__stream.close `close`]
|
||
|
|
function:
|
||
|
|
```
|
||
|
|
ws.close();
|
||
|
|
```
|
||
|
|
|
||
|
|
When the remote peer initiates a close by sending a close frame, Beast
|
||
|
|
will handle it for you by causing the next read to return `error::closed`.
|
||
|
|
When this error code is delivered, it indicates to the application that
|
||
|
|
the WebSocket connection has been closed cleanly, and that the TCP/IP
|
||
|
|
connection has been closed. After initiating a close, it is necessary to
|
||
|
|
continue reading messages until receiving the error `error::closed`. This
|
||
|
|
is because the remote peer may still be sending message and control frames
|
||
|
|
before it receives and responds to the close frame.
|
||
|
|
|
||
|
|
[important
|
||
|
|
To receive the
|
||
|
|
[link beast.ref.websocket__error `error::closed`]
|
||
|
|
error, a read operation is required.
|
||
|
|
]
|
||
|
|
|
||
|
|
[heading Auto-fragment]
|
||
|
|
|
||
|
|
To ensure timely delivery of control frames, large messages can be broken up
|
||
|
|
into smaller sized frames. The automatic fragment option turns on this
|
||
|
|
feature, and the write buffer size option determines the maximum size of
|
||
|
|
the fragments:
|
||
|
|
```
|
||
|
|
...
|
||
|
|
ws.set_option(websocket::auto_fragment{true});
|
||
|
|
ws.set_option(websocket::write_buffer_size{16384});
|
||
|
|
```
|
||
|
|
|
||
|
|
[endsect]
|