1<html> 2<head> 3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 4<title>Messages</title> 5<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css"> 6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1"> 7<link rel="home" href="../../index.html" title="Chapter 1. Boost.Beast"> 8<link rel="up" href="../using_websocket.html" title="WebSocket"> 9<link rel="prev" href="decorator.html" title="Decorator"> 10<link rel="next" href="control_frames.html" title="Control Frames"> 11</head> 12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> 13<table cellpadding="2" width="100%"><tr> 14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td> 15<td align="center"><a href="../../../../../../index.html">Home</a></td> 16<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td> 17<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> 18<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> 19<td align="center"><a href="../../../../../../more/index.htm">More</a></td> 20</tr></table> 21<hr> 22<div class="spirit-nav"> 23<a accesskey="p" href="decorator.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../using_websocket.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="control_frames.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> 24</div> 25<div class="section"> 26<div class="titlepage"><div><div><h3 class="title"> 27<a name="beast.using_websocket.messages"></a><a class="link" href="messages.html" title="Messages">Messages</a> 28</h3></div></div></div> 29<p> 30 Once a websocket session is established, messages can be sent unsolicited 31 by either peer at any time. A message is made up of one or more <span class="emphasis"><em>messages 32 frames</em></span>. Each frame is prefixed with the size of the payload in 33 bytes, followed by the data. A frame also contains a flag (called 'fin') 34 indicating whether or not it is the last frame of the message. When a message 35 is made up from only one frame, it is possible to know immediately what the 36 size of the message will be. Otherwise, the total size of the message can 37 only be determined once the last frame is received. 38 </p> 39<p> 40 The boundaries between frames of a multi-frame message are not not considered 41 part of the message. Intermediaries such as proxies which forward the websocket 42 traffic are free to "reframe" (split frames and combine them) the 43 message in arbitrary ways. These intermediaries include Beast, which can 44 reframe messages automatically in some cases depending on the options set 45 on the stream. 46 </p> 47<div class="caution"><table border="0" summary="Caution"> 48<tr> 49<td rowspan="2" align="center" valign="top" width="25"><img alt="[Caution]" src="../../../../../../doc/src/images/caution.png"></td> 50<th align="left">Caution</th> 51</tr> 52<tr><td align="left" valign="top"><p> 53 An algorithm should never depend on the way that incoming or outgoing messages 54 are split up into frames. 55 </p></td></tr> 56</table></div> 57<p> 58 Messages can be either text or binary. A message sent as text must contain 59 consist of valid utf8, while a message sent as binary may contain arbitrary 60 data. In addition to message frames, websocket provides <span class="emphasis"><em>control 61 frames</em></span> in the form of ping, pong, and close messages which have 62 a small upper limit on their payload size. Depending on how a message is 63 framed, control frames may have more opportunities to be sent in-between. 64 </p> 65<h5> 66<a name="beast.using_websocket.messages.h0"></a> 67 <span class="phrase"><a name="beast.using_websocket.messages.sending"></a></span><a class="link" href="messages.html#beast.using_websocket.messages.sending">Sending</a> 68 </h5> 69<p> 70 These stream members are used to write websocket messages: 71 </p> 72<div class="table"> 73<a name="beast.using_websocket.messages.websocket_stream_write_operation"></a><p class="title"><b>Table 1.33. WebSocket Stream Write Operations</b></p> 74<div class="table-contents"><table class="table" summary="WebSocket Stream Write Operations"> 75<colgroup> 76<col> 77<col> 78</colgroup> 79<thead><tr> 80<th> 81 <p> 82 Function 83 </p> 84 </th> 85<th> 86 <p> 87 Description 88 </p> 89 </th> 90</tr></thead> 91<tbody> 92<tr> 93<td> 94 <p> 95 <a class="link" href="../ref/boost__beast__websocket__stream/write/overload2.html" title="websocket::stream::write (2 of 2 overloads)"><code class="computeroutput"><span class="identifier">write</span></code></a>, <a class="link" href="../ref/boost__beast__websocket__stream/async_write.html" title="websocket::stream::async_write"><code class="computeroutput"><span class="identifier">async_write</span></code></a> 96 </p> 97 </td> 98<td> 99 <p> 100 Send a buffer sequence as a complete message. 101 </p> 102 </td> 103</tr> 104<tr> 105<td> 106 <p> 107 <a class="link" href="../ref/boost__beast__websocket__stream/write_some/overload2.html" title="websocket::stream::write_some (2 of 2 overloads)"><code class="computeroutput"><span class="identifier">write_some</span></code></a>, <a class="link" href="../ref/boost__beast__websocket__stream/async_write_some.html" title="websocket::stream::async_write_some"><code class="computeroutput"><span class="identifier">async_write_some</span></code></a> 108 </p> 109 </td> 110<td> 111 <p> 112 Send a buffer sequence as part of a message. 113 </p> 114 </td> 115</tr> 116</tbody> 117</table></div> 118</div> 119<br class="table-break"><p> 120 This example shows how to send a buffer sequence as a complete message. 121 </p> 122<pre class="programlisting"><span class="identifier">net</span><span class="special">::</span><span class="identifier">const_buffer</span> <span class="identifier">b</span><span class="special">(</span><span class="string">"Hello, world!"</span><span class="special">,</span> <span class="number">13</span><span class="special">);</span> 123 124<span class="comment">// This sets all outgoing messages to be sent as text.</span> 125<span class="comment">// Text messages must contain valid utf8, this is checked</span> 126<span class="comment">// when reading but not when writing.</span> 127 128<span class="identifier">ws</span><span class="special">.</span><span class="identifier">text</span><span class="special">(</span><span class="keyword">true</span><span class="special">);</span> 129 130<span class="comment">// Write the buffer as text</span> 131<span class="identifier">ws</span><span class="special">.</span><span class="identifier">write</span><span class="special">(</span><span class="identifier">b</span><span class="special">);</span> 132</pre> 133<p> 134 The same message could be sent in two or more frames thusly. 135 </p> 136<h5> 137<a name="beast.using_websocket.messages.h1"></a> 138 <span class="phrase"><a name="beast.using_websocket.messages.receiving"></a></span><a class="link" href="messages.html#beast.using_websocket.messages.receiving">Receiving</a> 139 </h5> 140<div class="table"> 141<a name="beast.using_websocket.messages.websocket_stream_read_operations"></a><p class="title"><b>Table 1.34. WebSocket Stream Read Operations</b></p> 142<div class="table-contents"><table class="table" summary="WebSocket Stream Read Operations"> 143<colgroup> 144<col> 145<col> 146</colgroup> 147<thead><tr> 148<th> 149 <p> 150 Function 151 </p> 152 </th> 153<th> 154 <p> 155 Description 156 </p> 157 </th> 158</tr></thead> 159<tbody> 160<tr> 161<td> 162 <p> 163 <a class="link" href="../ref/boost__beast__websocket__stream/read/overload2.html" title="websocket::stream::read (2 of 2 overloads)"><code class="computeroutput"><span class="identifier">read</span></code></a>, <a class="link" href="../ref/boost__beast__websocket__stream/async_read.html" title="websocket::stream::async_read"><code class="computeroutput"><span class="identifier">async_read</span></code></a> 164 </p> 165 </td> 166<td> 167 <p> 168 Read a complete message into a <a class="link" href="../concepts/DynamicBuffer.html" title="DynamicBuffer"><span class="emphasis"><em>DynamicBuffer</em></span></a>. 169 </p> 170 </td> 171</tr> 172<tr> 173<td> 174 <p> 175 <a class="link" href="../ref/boost__beast__websocket__stream/read_some/overload2.html" title="websocket::stream::read_some (2 of 4 overloads)"><code class="computeroutput"><span class="identifier">read_some</span></code></a>, <a class="link" href="../ref/boost__beast__websocket__stream/async_read_some/overload1.html" title="websocket::stream::async_read_some (1 of 2 overloads)"><code class="computeroutput"><span class="identifier">async_read_some</span></code></a> 176 </p> 177 </td> 178<td> 179 <p> 180 Read part of a message into a <a class="link" href="../concepts/DynamicBuffer.html" title="DynamicBuffer"><span class="emphasis"><em>DynamicBuffer</em></span></a>. 181 </p> 182 </td> 183</tr> 184<tr> 185<td> 186 <p> 187 <a class="link" href="../ref/boost__beast__websocket__stream/read_some/overload4.html" title="websocket::stream::read_some (4 of 4 overloads)"><code class="computeroutput"><span class="identifier">read_some</span></code></a>, <a class="link" href="../ref/boost__beast__websocket__stream/async_read_some/overload2.html" title="websocket::stream::async_read_some (2 of 2 overloads)"><code class="computeroutput"><span class="identifier">async_read_some</span></code></a> 188 </p> 189 </td> 190<td> 191 <p> 192 Read part of a message into a <a href="../../../../../../doc/html/boost_asio/reference/MutableBufferSequence.html" target="_top"><span class="emphasis"><em>MutableBufferSequence</em></span></a>. 193 </p> 194 </td> 195</tr> 196</tbody> 197</table></div> 198</div> 199<br class="table-break"><p> 200 After the WebSocket handshake is accomplished, callers may send and receive 201 messages using the message oriented interface. This interface requires that 202 all of the buffers representing the message are known ahead of time: 203 </p> 204<pre class="programlisting"><span class="comment">// This DynamicBuffer will hold the received message</span> 205<span class="identifier">flat_buffer</span> <span class="identifier">buffer</span><span class="special">;</span> 206 207<span class="comment">// Read a complete message into the buffer's input area</span> 208<span class="identifier">ws</span><span class="special">.</span><span class="identifier">read</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">);</span> 209 210<span class="comment">// Set text mode if the received message was also text,</span> 211<span class="comment">// otherwise binary mode will be set.</span> 212<span class="identifier">ws</span><span class="special">.</span><span class="identifier">text</span><span class="special">(</span><span class="identifier">ws</span><span class="special">.</span><span class="identifier">got_text</span><span class="special">());</span> 213 214<span class="comment">// Echo the received message back to the peer. If the received</span> 215<span class="comment">// message was in text mode, the echoed message will also be</span> 216<span class="comment">// in text mode, otherwise it will be in binary mode.</span> 217<span class="identifier">ws</span><span class="special">.</span><span class="identifier">write</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">.</span><span class="identifier">data</span><span class="special">());</span> 218 219<span class="comment">// Discard all of the bytes stored in the dynamic buffer,</span> 220<span class="comment">// otherwise the next call to read will append to the existing</span> 221<span class="comment">// data instead of building a fresh message.</span> 222<span class="identifier">buffer</span><span class="special">.</span><span class="identifier">consume</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">.</span><span class="identifier">size</span><span class="special">());</span> 223</pre> 224<div class="important"><table border="0" summary="Important"> 225<tr> 226<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../../../../doc/src/images/important.png"></td> 227<th align="left">Important</th> 228</tr> 229<tr><td align="left" valign="top"><p> 230 <a class="link" href="../ref/boost__beast__websocket__stream.html" title="websocket::stream"><code class="computeroutput"><span class="identifier">websocket</span><span class="special">::</span><span class="identifier">stream</span></code></a> is not thread-safe. Calls 231 to stream member functions must all be made from the same implicit or explicit 232 strand. 233 </p></td></tr> 234</table></div> 235<h5> 236<a name="beast.using_websocket.messages.h2"></a> 237 <span class="phrase"><a name="beast.using_websocket.messages.frames"></a></span><a class="link" href="messages.html#beast.using_websocket.messages.frames">Frames</a> 238 </h5> 239<p> 240 Some use-cases make it impractical or impossible to buffer the entire message 241 ahead of time: 242 </p> 243<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 244<li class="listitem"> 245 Streaming multimedia to an endpoint. 246 </li> 247<li class="listitem"> 248 Sending a message that does not fit in memory at once. 249 </li> 250<li class="listitem"> 251 Providing incremental results as they become available. 252 </li> 253</ul></div> 254<p> 255 For these cases, the partial data oriented interface may be used. This example 256 reads and echoes a complete message using this interface: 257 </p> 258<pre class="programlisting"><span class="comment">// This DynamicBuffer will hold the received message</span> 259<span class="identifier">multi_buffer</span> <span class="identifier">buffer</span><span class="special">;</span> 260 261<span class="comment">// Read the next message in pieces</span> 262<span class="keyword">do</span> 263<span class="special">{</span> 264 <span class="comment">// Append up to 512 bytes of the message into the buffer</span> 265 <span class="identifier">ws</span><span class="special">.</span><span class="identifier">read_some</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">,</span> <span class="number">512</span><span class="special">);</span> 266<span class="special">}</span> 267<span class="keyword">while</span><span class="special">(!</span> <span class="identifier">ws</span><span class="special">.</span><span class="identifier">is_message_done</span><span class="special">());</span> 268 269<span class="comment">// At this point we have a complete message in the buffer, now echo it</span> 270 271<span class="comment">// The echoed message will be sent in binary mode if the received</span> 272<span class="comment">// message was in binary mode, otherwise we will send in text mode.</span> 273<span class="identifier">ws</span><span class="special">.</span><span class="identifier">binary</span><span class="special">(</span><span class="identifier">ws</span><span class="special">.</span><span class="identifier">got_binary</span><span class="special">());</span> 274 275<span class="comment">// This buffer adaptor allows us to iterate through buffer in pieces</span> 276<span class="identifier">buffers_suffix</span><span class="special"><</span><span class="identifier">multi_buffer</span><span class="special">::</span><span class="identifier">const_buffers_type</span><span class="special">></span> <span class="identifier">cb</span><span class="special">{</span><span class="identifier">buffer</span><span class="special">.</span><span class="identifier">data</span><span class="special">()};</span> 277 278<span class="comment">// Echo the received message in pieces.</span> 279<span class="comment">// This will cause the message to be broken up into multiple frames.</span> 280<span class="keyword">for</span><span class="special">(;;)</span> 281<span class="special">{</span> 282 <span class="keyword">if</span><span class="special">(</span><span class="identifier">buffer_bytes</span><span class="special">(</span><span class="identifier">cb</span><span class="special">)</span> <span class="special">></span> <span class="number">512</span><span class="special">)</span> 283 <span class="special">{</span> 284 <span class="comment">// There are more than 512 bytes left to send, just</span> 285 <span class="comment">// send the next 512 bytes. The value `false` informs</span> 286 <span class="comment">// the stream that the message is not complete.</span> 287 <span class="identifier">ws</span><span class="special">.</span><span class="identifier">write_some</span><span class="special">(</span><span class="keyword">false</span><span class="special">,</span> <span class="identifier">buffers_prefix</span><span class="special">(</span><span class="number">512</span><span class="special">,</span> <span class="identifier">cb</span><span class="special">));</span> 288 289 <span class="comment">// This efficiently discards data from the adaptor by</span> 290 <span class="comment">// simply ignoring it, but does not actually affect the</span> 291 <span class="comment">// underlying dynamic buffer.</span> 292 <span class="identifier">cb</span><span class="special">.</span><span class="identifier">consume</span><span class="special">(</span><span class="number">512</span><span class="special">);</span> 293 <span class="special">}</span> 294 <span class="keyword">else</span> 295 <span class="special">{</span> 296 <span class="comment">// Only 512 bytes or less remain, so write the whole</span> 297 <span class="comment">// thing and inform the stream that this piece represents</span> 298 <span class="comment">// the end of the message by passing `true`.</span> 299 <span class="identifier">ws</span><span class="special">.</span><span class="identifier">write_some</span><span class="special">(</span><span class="keyword">true</span><span class="special">,</span> <span class="identifier">cb</span><span class="special">);</span> 300 <span class="keyword">break</span><span class="special">;</span> 301 <span class="special">}</span> 302<span class="special">}</span> 303 304<span class="comment">// Discard all of the bytes stored in the dynamic buffer,</span> 305<span class="comment">// otherwise the next call to read will append to the existing</span> 306<span class="comment">// data instead of building a fresh message.</span> 307<span class="identifier">buffer</span><span class="special">.</span><span class="identifier">consume</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">.</span><span class="identifier">size</span><span class="special">());</span> 308</pre> 309</div> 310<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 311<td align="left"></td> 312<td align="right"><div class="copyright-footer">Copyright © 2016-2019 Vinnie 313 Falco<p> 314 Distributed under the Boost Software License, Version 1.0. (See accompanying 315 file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) 316 </p> 317</div></td> 318</tr></table> 319<hr> 320<div class="spirit-nav"> 321<a accesskey="p" href="decorator.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../using_websocket.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="control_frames.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> 322</div> 323</body> 324</html> 325