[/
    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:asio_refresher 回顾]

为有效使用 Beast，需要预先理解网络库相关知识。本节对这些概念进行回顾，以作为提醒及进一步学习的指引。

[@https://en.wikipedia.org/wiki/Computer_network [网络]] 允许位于任意地点的程序在建立 [@https://en.wikipedia.org/wiki/Data_link [连接]] 并选择通信后进行信息交换。数据可通过连接在双向（[@https://en.wikipedia.org/wiki/Duplex_(telecommunications) [全双工]]）上可靠传输，且字节按发送顺序到达。这些连接以及用于表示连接的对象和类型统称为 [link beast.concepts.streams [流]]。连接到网络的计算机或设备称为 [@https://en.wikipedia.org/wiki/Host_(network) [主机]]，已建立连接另一端的程序称为 [@https://en.wikipedia.org/wiki/Peer-to-peer [对等端]]。

[@https://en.wikipedia.org/wiki/Internet [互联网]] 是一个由全球互联计算机组成的网络，这些计算机使用多种标准化的通信协议进行信息交换。其中最为流行的协议是 [@https://en.wikipedia.org/wiki/Transmission_Control_Protocol [TCP/IP]]，这也是本库唯一依赖的协议。该协议处理了底层细节，使得应用程序看到的是一个可靠的、全双工的流式连接，用于承载上述有序字节序列。[@https://en.wikipedia.org/wiki/Server_(computing) [服务器]] 是一台强大的、始终在线的主机，位于知名的网络名称或地址上，用于提供数据服务。而 [@https://en.wikipedia.org/wiki/Client_(computing) [客户端]] 则是一个临时的对等端，它连接到服务器进行数据交换，完成后便离线。

[@https://en.wikipedia.org/wiki/Internet [互联网]] 是一个由全球互联计算机组成的网络，这些计算机使用多种标准化的通信协议进行信息交换。其中最为流行的协议是 [@https://en.wikipedia.org/wiki/Transmission_Control_Protocol [TCP/IP]]，这也是本库唯一依赖的协议。该协议处理了底层细节，使得应用程序看到的是一个可靠的、全双工的流式连接，用于承载上述有序字节序列。[@https://en.wikipedia.org/wiki/Server_(computing) [服务器]] 是一台强大的、始终在线的主机，位于知名的网络名称或地址上，用于提供数据服务。而 [@https://en.wikipedia.org/wiki/Client_(computing) [客户端]] 则是一个临时的对等端，它连接到服务器进行数据交换，完成后便离线。

C++ 中的网络编程以 __Asio__、[@https://think-async.com/Asio/ Asio] 以及 __NetTS__ 为代表，提供了一个抽象层，用于可移植地与操作系统设施交互。这些设施不仅涵盖网络，还涉及通用的 [@https://en.wikipedia.org/wiki/Input/output [输入/输出]]（简称 I/O）。

[/-----------------------------------------------------------------------------]

[heading 缓冲区]

[@https://en.wikipedia.org/wiki/Data_buffer [缓冲区]] 是用于存放 I/O 操作中字节数据的一段连续内存区域。[@boost:/doc/html/boost_asio/reference/const_buffer.html `net::const_buffer`] 与 [@boost:/doc/html/boost_asio/reference/mutable_buffer.html `net::mutable_buffer`] 类型以类型安全的指针/大小对来表示这些内存区域。

[code_core_1_refresher_1s]

[tip
    `const_buffer` 与 `mutable_buffer` 比 `std::span<byte>` 更适用。
    and `span<byte const>` because
    [@https://en.cppreference.com/w/cpp/container/span `std::span`]
    does too much. It not only
    type-erases the original pointer but also recasts it to a pointer-to-byte.
    The operating system doesn't care about this, but if a user wants to send
    and receive an array of some other type, presenting it as an array of bytes
    which supports bitwise operations is unnecessary. Custom buffer types also
    enable implementations to provide targeted features such as
    [@boost:/doc/html/boost_asio/overview/core/buffers.html#boost_asio.overview.core.buffers.buffer_debugging ['buffer debugging]]
    without changing the more general vocabulary types.
]

__ConstBufferSequence__ 与 __MutableBufferSequence__ 概念用于描述双向范围，其值类型分别可转换为 `const_buffer` 与 `mutable_buffer`。这些序列允许在单个函数调用中处理多个缓冲区，这种技术称为 [@https://en.wikipedia.org/wiki/Vectored_I/O [分散/聚集 I/O]]。缓冲区及缓冲区序列不具有所有权；拷贝操作产生的是浅层引用，而非底层内存的副本。以下每条语句都用于声明一个缓冲区序列：

[code_core_1_refresher_2s]

[@boost:/doc/html/boost_asio/reference/buffer_size.html `net::buffer_size`] 函数用于确定缓冲区序列中的总字节数，而 [@boost:/doc/html/boost_asio/reference/buffer_copy.html `net::buffer_copy`] 函数则用于将部分或全部字节从一个缓冲区序列转移到另一个序列。`buffer_size` 是一个定制点：允许用户在外层命名空间中定义重载版本，调用时不应使用命名空间限定符。[@boost:/doc/html/boost_asio/reference/buffer_sequence_begin.html `net::buffer_sequence_begin`] 与 [@boost:/doc/html/boost_asio/reference/buffer_sequence_end.html `net::buffer_sequence_end`] 函数用于获取遍历序列的一对迭代器。Beast 提供了一系列缓冲区序列类型和算法，包括 [link beast.ref.boost__beast__buffers_cat `buffers_cat`]、[link beast.ref.boost__beast__buffers_front `buffers_front`]、[link beast.ref.boost__beast__buffers_prefix `buffers_prefix`]、[link beast.ref.boost__beast__buffers_range `buffers_range`] 以及 [link beast.ref.boost__beast__buffers_suffix `buffers_suffix`]。以下示例将缓冲区序列中的字节转换为字符串：

[code_core_1_refresher_1]

__DynamicBuffer__ 概念用于定义一个可调整大小的缓冲区序列接口。当内存需求无法预先确定时（例如从流中读取 HTTP 消息时），算法可以使用动态缓冲区来表达。Beast 提供一系列完善的动态缓冲区类型，包括 [link beast.ref.boost__beast__buffers_adaptor `buffers_adaptor`]、[link beast.ref.boost__beast__flat_buffer `flat_buffer`]、[link beast.ref.boost__beast__multi_buffer `multi_buffer`] 以及 [link beast.ref.boost__beast__static_buffer `static_buffer`]。以下函数从 [link beast.ref.boost__beast__tcp_stream `tcp_stream`] 中读取数据到动态缓冲区，直到遇到换行符为止，该函数使用 [@boost:/doc/html/boost_asio/reference/buffers_iterator.html `net::buffers_iterator`] 将缓冲区内容视为字符范围进行处理：

[code_core_1_refresher_2]



[/-----------------------------------------------------------------------------]

[heading 同步 I/O]

同步输入与输出通过阻塞函数调用实现，这些调用在操作完成后将返回结果。此类操作通常无法取消，也没有设置超时的方法。__SyncReadStream__ 与 __SyncWriteStream__ 概念用于定义 [同步流] 的要求：这是一种可移植的 I/O 抽象，使用缓冲区序列来传输字节数据，并通过 `error_code` 或异常来报告错误。[@boost:/doc/html/boost_asio/reference/basic_stream_socket.html `net::basic_stream_socket`] 是一种常用的同步流，用于建立 TCP/IP 连接。用户也可以定义满足这些要求的自定义类型。

[code_core_1_refresher_3]

同步流算法用于编写为函数模板，接受满足同步读写（或两者兼具）命名要求的流对象。以下示例用于展示一个写入文本并使用异常指示错误的算法：

[code_core_1_refresher_4]

同一算法也可采用错误码而非异常的方式来表述：

[code_core_1_refresher_5]

[/-----------------------------------------------------------------------------]

[heading 异步 I/O]

异步操作从调用 [@boost:/doc/html/boost_asio/reference/asynchronous_operations.html [发起函数]] 开始。该函数负责启动操作并立即返回，不会等待操作完成。随后，这个 [未完成] 的异步操作会在后台并发执行，不会阻塞调用者。当操作的外部可见效果全部产生后，发起函数中提供的一个可移动对象（称为 [@boost:/doc/html/boost_asio/reference/CompletionHandler.html [完成处理器]]）会连同操作结果（例如错误码及其他信息）一起被放入队列，等待执行。完成处理器被放入队列的那一刻，就意味着该异步操作 [已完成]。下面的代码演示了如何异步地向套接字写入一段文本，并在操作完成时调用一个 lambda 函数：

[code_core_1_refresher_3s]

每个完成处理器（也称为 [@https://en.wikipedia.org/wiki/Continuation [延续]]）都包含三个关联组件：通过 [@boost:/doc/html/boost_asio/reference/get_associated_allocator.html `net::get_associated_allocator`] 获取的 [@boost:/doc/html/boost_asio/overview/core/allocation.html [关联分配器]]、通过 [@boost:/doc/html/boost_asio/reference/associated_cancellation_slot.html `net::get_associated_cancellation_slot`] 获取的 [@boost:/doc/html/boost_asio/reference/associated_cancellation_slot.html [关联取消槽]]，以及通过 [@boost:/doc/html/boost_asio/reference/get_associated_executor.html `net::get_associated_executor`] 获取的 [@boost:/doc/html/boost_asio/reference/associated_executor.html [关联执行器]]。这些关联可以通过内嵌方式指定：

[code_core_1_refresher_6]

或者，这些关联也可以通过非侵入方式指定，即特化类模板 [@boost:/doc/html/boost_asio/reference/associated_allocator.html `net::associated_allocator`]、[@boost:/doc/html/boost_asio/reference/associated_cancellation_slot.html `net::associated_cancellation_slot`] 以及 [@boost:/doc/html/boost_asio/reference/associated_executor.html `net::associated_executor`]：

[code_core_1_refresher_7]

当调用方希望更改完成处理器的执行器时，可以使用 [@boost:/doc/html/boost_asio/reference/bind_executor.html `net::bind_executor`] 函数。

实现使用该分配器来获取执行操作所需的任何临时存储空间。所有临时分配的内存在完成处理器被调用之前都会被释放。执行器是一种轻量可复制的对象，提供用于调用完成处理器的算法。除非调用方进行了自定义，否则完成处理器默认使用 `std::allocator<void>` 以及对应 I/O 对象的执行器。

当调用方希望为操作指定自定义分配器时，可以使用 [@boost:/doc/html/boost_asio/reference/bind_allocator.html `net::bind_allocator`] 函数。


完成处理器令牌所关联的取消槽可用于取消单个操作。该取消槽通常由完成处理器令牌（例如 [@boost:/doc/html/boost_asio/reference/use_awaitable.html `net::use_awaitable`] 或 [@boost:/doc/html/boost_asio/reference/yield_context.html `net::yield_context`]）进行传递。 

可用的 [@boost:/doc/html/boost_asio/reference/cancellation_type.html 取消类型] 如下所列。

# `terminal` —— 终止型
    Requests cancellation where, following a successful cancellation, 
    the only safe operations on the I/O object are closure or destruction.

# `partial` —— 部分型
    Requests cancellation where a successful cancellation may result in partial 
    side effects or no side effects. Following cancellation, 
    the I/O object is in a well-known state, and may be used for further operations.

# `total` —— 完全型
    Requests cancellation where a successful cancellation results in no apparent side effects.
     Following cancellation, the I/O object is in the same observable state as it was prior to the operation.




网络库规定用于确定处理器运行上下文的设施。每个 I/O 对象都关联一个 __ExecutionContext__，用于获取调用完成处理器所需的 __Executor__ 实例。执行器决定完成处理器的调用位置与方式。从 __io_context__ 实例获取的执行器提供一项基本保证：处理器仅会在当前正在调用 [@boost:/doc/html/boost_asio/reference/io_context/run/overload1.html `net::io_context::run`] 的线程中被执行。

__AsyncReadStream__ 与 __AsyncWriteStream__ 概念用于定义 [异步流] 的要求：这是一种可移植的 I/O 抽象，能够异步交换数据，使用缓冲区序列表示字节数据，并通过 `error_code` 报告错误。[异步流算法] 以模板化的发起函数形式编写，接受满足异步读、异步写或两者兼具命名要求的流对象。以下示例用于展示一个向异步流写入文本的算法：

[code_core_1_refresher_8]

[/-----------------------------------------------------------------------------]

[heading 并发]

套接字和流等 I/O 对象 [*不是线程安全的]。尽管可以同时有多个操作未完成（例如，同时进行异步读和异步写），但流对象本身在同一时刻只能从一个线程进行访问。这意味着移动构造函数、析构函数或发起函数等成员函数不能并发调用。通常，这可以通过互斥锁等同步原语来实现，但并发网络程序需要更好的方式来访问共享资源，因为获取互斥锁的所有权可能会阻塞线程，使其无法执行无竞争的工作。为了提高效率，网络库采用了一种无需显式加锁的线程使用模型，要求所有对 I/O 对象的访问都必须在一个 [@boost:/doc/html/boost_asio/overview/core/strands.html [串行器]] 内执行。

[/-----------------------------------------------------------------------------]

[heading 通用模型]

由于完成处理器会导致控制流反转，有时需要其他方式来附加延续。网络库提供 [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3747.pdf [异步操作通用模型]]，该模型提供一种可定制的方法，用于改变发起函数的签名，以便使用其他类型的对象和方法来替代完成处理器回调。例如，使用 `std::future` 接收传输字节数来异步向套接字写入字符串的调用方式如下：

[code_core_1_refresher_4s]

此功能通过将变量 [@boost:/doc/html/boost_asio/reference/use_future.html `net::use_future`]（类型为 [@boost:/doc/html/boost_asio/reference/use_future_t.html `net::use_future_t<>`]）传递给完成处理器位置来实现。同一个 `async_write` 函数重载还可以与通过 [@boost:/doc/html/boost_asio/reference/spawn/overload1.html `asio::spawn`] 启动的 [@https://en.wikipedia.org/wiki/Fiber_(computer_science) [纤程]] 配合使用：

[code_core_1_refresher_5s]

在这两种情况下，都使用具有特定类型的对象来替代完成处理器，且发起函数的返回值也从 `void` 转变为 `std::future<std::size_t>` 或 `std::size_t`。在这种上下文中，该处理器有时被称为 __CompletionToken__。发起函数签名中的定制点支持这种返回值类型的转换。以下是 [@boost:/doc/html/boost_asio/reference/async_write/overload1.html `net::async_write`] 的签名：

需要注意的是，`spawn` 函数本身也带有完成签名，但示例中通过使用 `asio::detached` 忽略了它的结果。

[code_core_1_refresher_9]

函数返回值类型由 [@boost:/doc/html/boost_asio/reference/async_result.html `net::async_result`] 定制点决定。该定制点为 `std::future` 等常用库类型提供特化版本，同时也支持用户自定义类型的特化。发起函数的函数体通过调用 [@boost:/doc/html/boost_asio/reference/async_initiate.html `net::async_initiate`] 辅助函数来捕获参数并将其转发给 `async_result` 的特化版本。此外，还提供一个额外的“发起函数”对象，`async_result` 可利用该对象立即启动操作，或将操作启动延迟到未来某个时刻（即“延迟执行”）。该发起函数对象接收一个内部完成处理器，其签名与发起函数所期望的签名相匹配。

[code_core_1_refresher_10]

这个经过转换的内部处理器负责执行最终步骤，将操作结果传递给调用方。例如，当使用 `net::use_future` 时，内部处理器会通过调用发起函数返回的 promise 对象上的 [@https://en.cppreference.com/w/cpp/thread/promise/set_value `std::promise::set_value`] 来传递结果。

[/-----------------------------------------------------------------------------]

[heading 使用网络库]

大多数库中的流算法都需要一个已与远程对等端建立通信的 __socket__、__ssl_stream__ 或其他 __Stream__ 对象。以下示例用于回顾如何使用套接字：

[snippet_core_2]

在本文档中，以下名称的标识符具有特殊含义：

[table 全局变量
[[名称][描述]]
[[
    [@boost:/doc/html/boost_asio/reference/io_context.html [*`ioc`]]
][一个类型为 __io_context__ 的变量，该变量在单独线程上运行，且已为其构造一个 __executor_work_guard__ 对象。
]]
[[
    [@boost:/doc/html/boost_asio/reference/ip__tcp/socket.html [*`sock`]]
][一个类型为 [@boost:/doc/html/boost_asio/reference/ip__tcp/socket.html `tcp::socket`] 的变量，该变量已连接到远程主机。
]]
[[
    [@boost:/doc/html/boost_asio/reference/ssl__stream.html [*`ssl_sock`]]
][一个类型为 [@boost:/doc/html/boost_asio/reference/ssl__stream.html `net::ssl::stream<tcp::socket>`] 的变量，该变量已与远程主机建立连接并完成握手。
]]
[[
    [link beast.ref.boost__beast__websocket__stream [*`ws`]]
][一个类型为 [link beast.ref.boost__beast__websocket__stream `websocket::stream<tcp::socket>`] 的变量，该变量已与远程主机建立连接。
]]
]

[endsect]
