diff --git a/CHANGELOG.md b/CHANGELOG.md index be69d5ea..ccf14ae5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ Version 158: * Tidy up end_of_stream javadoc +* Tidy up websocket docs -------------------------------------------------------------------------------- diff --git a/doc/qbk/06_websocket/1_streams.qbk b/doc/qbk/06_websocket/1_streams.qbk index 47e7dbad..379dfc8a 100644 --- a/doc/qbk/06_websocket/1_streams.qbk +++ b/doc/qbk/06_websocket/1_streams.qbk @@ -78,4 +78,8 @@ accessed by calling operations are being performed may result in undefined behavior. ] +[heading Non-Blocking Mode] + +Please note that websocket streams do not support non-blocking modes. + [endsect] diff --git a/doc/qbk/06_websocket/5_messages.qbk b/doc/qbk/06_websocket/5_messages.qbk index 37d42c43..149c3b65 100644 --- a/doc/qbk/06_websocket/5_messages.qbk +++ b/doc/qbk/06_websocket/5_messages.qbk @@ -61,9 +61,9 @@ all of the buffers representing the message are known ahead of time: [ws_snippet_15] [important - Calls to [link beast.ref.boost__beast__websocket__stream.set_option `set_option`] - must be made from the same implicit or explicit strand as that used - to perform other operations. + [link beast.ref.boost__beast__websocket__stream `websocket::stream`] + is not thread-safe. Calls to stream member functions must + all be made from the same implicit or explicit strand. ] [heading Frames] diff --git a/test/doc/websocket_snippets.cpp b/test/doc/websocket_snippets.cpp index ec356146..9b27e76d 100644 --- a/test/doc/websocket_snippets.cpp +++ b/test/doc/websocket_snippets.cpp @@ -152,11 +152,24 @@ boost::asio::ip::tcp::socket sock{ioc}; { stream ws{ioc}; //[ws_snippet_15 + // This DynamicBuffer will hold the received message multi_buffer buffer; + + // Read a complete message into the buffer's input area ws.read(buffer); + // Set text mode if the received message was also text, + // otherwise binary mode will be set. ws.text(ws.got_text()); + + // Echo the received message back to the peer. If the received + // message was in text mode, the echoed message will also be + // in text mode, otherwise it will be in binary mode. ws.write(buffer.data()); + + // Discard all of the bytes stored in the dynamic buffer, + // otherwise the next call to read will append to the existing + // data instead of building a fresh message. buffer.consume(buffer.size()); //] } @@ -164,26 +177,56 @@ boost::asio::ip::tcp::socket sock{ioc}; { stream ws{ioc}; //[ws_snippet_16 + // This DynamicBuffer will hold the received message multi_buffer buffer; - for(;;) - if(ws.read_some(buffer, 0)) - break; + + // Read the next message in pieces + do + { + // Append up to 512 bytes of the message into the buffer + ws.read_some(buffer, 512); + } + while(! ws.is_message_done()); + + // At this point we have a complete message in the buffer, now echo it + + // The echoed message will be sent in binary mode if the received + // message was in binary mode, otherwise we will send in text mode. ws.binary(ws.got_binary()); + + // This buffer adapter allows us to iterate through buffer in pieces buffers_suffix cb{buffer.data()}; + + // Echo the received message in pieces. + // This will cause the message to be broken up into multiple frames. for(;;) { using boost::asio::buffer_size; if(buffer_size(cb) > 512) { + // There are more than 512 bytes left to send, just + // send the next 512 bytes. The value `false` informs + // the stream that the message is not complete. ws.write_some(false, buffers_prefix(512, cb)); + + // This efficiently discards data from the adapter by + // simply ignoring it, but does not actually affect the + // underlying dynamic buffer. cb.consume(512); } else { + // Only 512 bytes or less remain, so write the whole + // thing and inform the stream that this piece represents + // the end of the message by passing `true`. ws.write_some(true, cb); break; } } + + // Discard all of the bytes stored in the dynamic buffer, + // otherwise the next call to read will append to the existing + // data instead of building a fresh message. //] }