[/
    Copyright (c) 2016-2019 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)

    Official repository: https://github.com/boostorg/beast
]

[section 控制帧]

控制帧是小型消息（小于 128 字节），完全包含在单个 WebSocket 帧中。已建立连接的任意一端可以在任何时间发送控制帧，并且控制帧可以出现在消息的连续帧之间。控制帧分为三种类型：ping、pong 和 close。

发送 ping 表示发送方希望收到 pong 响应。pong 是对 ping 的回复，也可以在任何时候主动发送。主动发送 pong 的一个用途是，在长时间没有数据传输时，告知远端对端连接仍然活跃。close 帧表示对端请求关闭 WebSocket 连接。当双方都完成发送并接收到 close 帧后，连接视为已正常关闭。

在执行读取操作期间，Beast 会自动读取并处理控制帧。如果注册了控制回调函数，该回调会收到传入控制帧的通知。实现会自动响应 ping。当收到 close 帧时，会触发 WebSocket 关闭流程，最终在后续的读取操作中（假设没有发生其他错误）向调用方传递错误码 [link beast.ref.boost__beast__websocket__error error::closed]。

这种自动行为会导致一个后果：调用方发起的读操作，可能触发套接字写入。但这类写入不会与调用方主动发起的写操作产生竞争。从流不变性的正确性来看，调用方发起的读操作仍只视为读取。这意味着调用方可同时进行读、写和 ping/pong 操作，同时实现也会在后台自动处理控制帧。

[heading 控制回调]

ping、pong 和 close 消息属于控制帧，在已建立的 WebSocket 连接上，任何一端都可以随时发送。它们分别通过 [link beast.ref.boost__beast__websocket__stream.ping `ping`]、[link beast.ref.boost__beast__websocket__stream.pong `pong`] 和 [link beast.ref.boost__beast__websocket__stream.close `close`] 函数发送。若要接收控制帧的通知，调用方可通过 [link beast.ref.boost__beast__websocket__stream.control_callback `control_callback`] 注册一个控制回调。该选项提供的对象应满足以下签名要求：

[code_websocket_5_1]

当注册控制回调后，无论是通过同步读函数还是异步读函数接收到的所有 ping、pong 和 close 帧，都会触发该回调。帧类型和有效载荷文本会作为参数传递给控制回调。如果帧为 close 帧，可通过调用 [link beast.ref.boost__beast__websocket__stream.reason `reason`] 获取关闭原因。

与异步发起函数调用中使用的普通完成处理器不同，控制回调只需设置一次，调用后不会被重置。该回调同时用于同步和异步读取。回调是“被动”的——必须有一个流读取操作处于活动状态，回调才会被触发。

[note
    当异步读函数收到控制帧时，
    control callback is invoked in the same manner as that used to
    invoke the final completion handler of the corresponding read
    function.
]

[heading 关闭帧]

WebSocket 协议定义了启动会话关闭的过程和控制消息。在该过程中，主机通过发送 [@https://tools.ietf.org/html/rfc6455#section-5.5.1 关闭帧] 来请求关闭。若要请求关闭，可使用 `close` 或 `async_close` 等关闭函数：

[code_websocket_5_2]

关闭函数会发送关闭帧，然后读取并丢弃所有传入的消息数据，直到收到关闭帧为止，最后在返回之前关闭底层连接。

当读操作期间收到关闭帧时，实现会自动回复一个关闭帧，然后在返回之前关闭底层连接。在这种情况下，读操作会以错误码 [link beast.ref.boost__beast__websocket__error `error::closed`] 完成，这表示连接已被正常关闭。

[important
    要接受
    [link beast.ref.boost__beast__websocket__error `error::closed`]
    error, a read operation is required.
]

[heading 自动分帧]

为确保控制帧的及时传递，可以将较大的出站消息拆分为较小的帧。自动分片选项用于开启此功能，而写入缓冲区大小选项则决定分片的最大大小：

[code_websocket_5_3]

[endsect]
