mirror of
https://github.com/boostorg/beast.git
synced 2025-07-29 20:37:31 +02:00
@ -10,6 +10,7 @@ HTTP
|
||||
WebSocket
|
||||
|
||||
* Write buffer option does not change capacity
|
||||
* Close connection during async_read on close frame
|
||||
|
||||
Core
|
||||
|
||||
|
@ -14,8 +14,7 @@
|
||||
<member><link linkend="beast.websocket.handshaking">Handshaking</link></member>
|
||||
<member><link linkend="beast.websocket.messages">Messages</link></member>
|
||||
<member><link linkend="beast.websocket.frames">Frames</link></member>
|
||||
<member><link linkend="beast.websocket.controlframes">Control frames</link></member>
|
||||
<member><link linkend="beast.websocket.pongs">Pong messages</link></member>
|
||||
<member><link linkend="beast.websocket.control">Control Frames</link></member>
|
||||
<member><link linkend="beast.websocket.buffers">Buffers</link></member>
|
||||
<member><link linkend="beast.websocket.async">Asynchronous interface</link></member>
|
||||
<member><link linkend="beast.websocket.io_service">The io_service</link></member>
|
||||
@ -292,42 +291,45 @@ void echo(beast::websocket::stream<boost::asio::ip::tcp::socket>& ws)
|
||||
|
||||
|
||||
|
||||
[section:controlframes Control frames]
|
||||
[section:control Control Frames]
|
||||
|
||||
During read operations, the implementation automatically reads and processes
|
||||
WebSocket control frames such as ping, pong, and close. Pings are replied
|
||||
to as soon as possible, pongs are delivered to the pong 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
|
||||
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
|
||||
pongs are delivered to the pong 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.
|
||||
|
||||
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(beast::websocket::auto_fragment{true});
|
||||
ws.set_option(beast::websocket::write_buffer_size{16384});
|
||||
```
|
||||
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 simultaneous active read and write operation in progress, while
|
||||
the implementation also automatically handles control 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
|
||||
[link beast.ref.websocket__stream.close `close`]:
|
||||
```
|
||||
ws.close();
|
||||
```
|
||||
[heading Ping and Pong Frames]
|
||||
|
||||
[note To receive the [link beast.ref.websocket__error `error::closed`]
|
||||
error, a read operation is required. ]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
[section:pongs Pong messages]
|
||||
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.ping `pong`].
|
||||
|
||||
To receive pong control frames, callers may register a "pong callback" using
|
||||
[link beast.ref.websocket__stream.set_option `set_option`]. The object provided
|
||||
@ -348,9 +350,47 @@ reset when a pong is received. The same callback is used for both synchronous
|
||||
and asynchronous reads. The pong callback is passive; in order to receive
|
||||
pongs, a synchronous or asynchronous stream read function must be active.
|
||||
|
||||
[note When an asynchronous read function receives a pong, the the pong callback
|
||||
is invoked in the same manner as that used to invoke the final completion
|
||||
handler of the corresponding read function.]
|
||||
[note
|
||||
When an asynchronous read function receives a pong, the the pong
|
||||
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(beast::websocket::auto_fragment{true});
|
||||
ws.set_option(beast::websocket::write_buffer_size{16384});
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
|
@ -162,6 +162,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
||||
do_pong = 11,
|
||||
do_close_resume = 13,
|
||||
do_close = 15,
|
||||
do_teardown = 16,
|
||||
do_fail = 18,
|
||||
|
||||
do_call_handler = 99
|
||||
@ -379,9 +380,8 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
||||
d.state = do_close;
|
||||
break;
|
||||
}
|
||||
// call handler;
|
||||
ec = error::closed;
|
||||
goto upcall;
|
||||
d.state = do_teardown;
|
||||
break;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
@ -454,7 +454,7 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
||||
//------------------------------------------------------------------
|
||||
|
||||
case do_close:
|
||||
d.state = do_close + 1;
|
||||
d.state = do_teardown;
|
||||
d.ws.wr_close_ = true;
|
||||
BOOST_ASSERT(! d.ws.wr_block_);
|
||||
d.ws.wr_block_ = &d;
|
||||
@ -462,13 +462,15 @@ operator()(error_code ec,std::size_t bytes_transferred, bool again)
|
||||
d.fb.data(), std::move(*this));
|
||||
return;
|
||||
|
||||
case do_close + 1:
|
||||
d.state = do_close + 2;
|
||||
//------------------------------------------------------------------
|
||||
|
||||
case do_teardown:
|
||||
d.state = do_teardown + 1;
|
||||
websocket_helpers::call_async_teardown(
|
||||
d.ws.next_layer(), std::move(*this));
|
||||
return;
|
||||
|
||||
case do_close + 2:
|
||||
case do_teardown + 1:
|
||||
// call handler
|
||||
ec = error::closed;
|
||||
goto upcall;
|
||||
|
Reference in New Issue
Block a user