<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="">与 Zaphoyd Studios WebSocket++ 的对比</string>
    <string name="">变量列表\n\n[[1. 同步接口][\n\nBeast 提供了对 WebSocket 的全面支持，采用同步接口。它使用与 Boost.Asio 中相同的接口风格：抛出异常的版本，以及通过引用参数返回错误码的版本。\n\n[表格 [ [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]] [websocketpp] ][ [template&lt;class DynamicBuffer&gt; void read(DynamicBuffer&amp; dynabuf)] [ /&lt;不可用&gt;/ ] ]]]]\n\n[[2. 连接模型][\n\nWebSocketpp 通过使用一种特质——config::transport_type——支持多种传输方式（参见[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/connection.hpp#L60 asio传输示例]）。若想了解实现传输的复杂性，可对比一下asio传输与[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L59 iostream传输]（这是一种允许通过std::iostream进行WebSocket通信的层）。\n\n相比之下，Beast通过仅定义一个[NextLayer]模板参数来抽象传输。[NextLayer]的类型要求对用户而言早已熟悉，因为这些要求已在Asio中进行了文档化：AsyncReadStream、AsyncWriteStream、SyncReadStream、SyncWriteStream。\n\n使用用户自定义类型实例化beast::websocket::stream与websocketpp::connection时，类型要求大幅降低（从18个函数降至2个）。需要注意的是，websocketpp连接是以shared_ptr形式传递的。而Beast在其公共接口中任何地方均未使用shared_ptr。beast::websocket::stream的构造和移动方式与boost::asio::ip::tcp::socket完全一致。调用者如果需要，可以将此类对象放入shared_ptr中，但并非必须如此。 [表格 [ [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp Beast]] [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L234 websocketpp]] ][ [template&lt;class NextLayer&gt; class stream { NextLayer next_layer_; ... }] [template &lt;typename config&gt; class connection : public config::transport_type::transport_con_type , public config::connection_base { public: typedef lib::shared_ptr&lt;type&gt; ptr; ... }] ]]]]\n\n[[3. 客户端与服务器角色][\n\nWebSocketpp 通过不同类别的层次结构提供了多角色支持。beast::websocket::stream 不依赖于特定角色，它在同一类中提供成员函数，以同时执行客户端和服务器的握手操作。客户端和服务器流均使用相同的类型。\n\n[表格 [ [兽] [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/server_endpoint.hpp#L39 websocketpp], [@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/client_endpoint.hpp#L42 同样]] ][ [ /&lt;无需填写&gt;/ ] [模板 &lt;typename 配置&gt; 类客户端 : 公共 endpoint&lt;连接&lt;配置&gt;,配置&gt;; 模板 &lt;typename 配置&gt; 类服务器 : 公共 endpoint&lt;连接&lt;配置&gt;,配置&gt;;] ]]]]\n\n[[4. 线程安全][\n\nWebSocketpp 使用互斥锁来保护共享数据，防止并发访问。相比之下，Beast 在其整个实现中并未使用任何互斥锁。相反，它遵循了Asio模式：对异步启动函数的调用，采用与调用最终处理程序相同的机制，即通过关联的执行器机制来调用中间处理程序。 Beast的唯一要求是，对异步启动函数的调用必须来自同一隐式或显式线程。例如，如果与beast::websocket::stream关联的io_context是单线程的，则这被视为隐式线程，因此不会产生与互斥锁相关的性能开销。\n\n[表格 [ [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/read_frame_op.ipp#L118 Beast]] [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L706 websocketpp]] ][ [mutex_type m_read_mutex;] ]]]]\n\n[[5. 回调模型][\n\nwebsocketpp 需要对其实现接口中的每个事件（例如，消息接收时）进行一次调用，以设置相应的处理程序。该处理程序由一个等效于 std::function 的对象表示。需要注意的是，websocketpp 接口会对此处理程序执行类型擦除操作。\n\n相比之下，Beast处理器的定义方式与Boost.Asio完全一致。它们是函数对象，可以进行复制或移动操作，但最重要的是，它们不会进行类型擦除。编译器能够直接通过类型识别其实现细节，从而实现优化。此外，Beast遵循Asio关于处理器处理的规则：它会通过使用基于参数依赖查找的函数重载（例如bind_allocator），尊重与处理器相关联的任何分配、执行器和取消操作。 在调用站点提供了“兽”完成处理程序。对于每次对异步启动函数的调用，都保证恰好会有一 次对该处理程序的最终调用。此功能与Boost.Asio中提供的异步启动函数完全相同，从而支持更高级别抽象的组合。 [表格 [ [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L834 Beast]] [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L281 websocketpp], [@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L473 也]] ][ [模板&lt; 类型 DynamicBuffer, // 支持用户自定义类型 类型 ReadHandler // 处理器不进行类型擦除 &gt; typename async_completion&lt; // 返回值定制 ReadHandler, // 支持 futures 和协程 void(error_code) &gt;::result_type async_read( DynamicBuffer&amp; dynabuf, ReadHandler&amp;&amp; handler);] [使用 lib::function&lt; void(connection_hdl,message_ptr) &gt; message_handler; void set_message_handler(message_handler h);] ]]]]\n\n[[6. 可扩展的异步模型][\n\nBeast完全支持由Boost.Asio作者克里斯托弗·科尔霍夫所开发的[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3896.pdf 可扩展异步模型]（参见第8节）。\n\nBeast WebSocket 异步接口可与 std::future 栈式/非栈式协程，或用户自定义的定制化功能无缝配合使用。\n\n[表格 [ [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/stream.ipp#L378 Beast]] [websocketpp] ][ [``` beast::async_completion&lt; ReadHandler, void(error_code)&gt; completion{handler}; read_op&lt; DynamicBuffer, decltype(completion.handler)&gt;{ completion.handler, *this, op, buffer};\n\n返回 completion.result.get(); // 自定义点 ```] [ /&lt;不可用&gt;/ ] ]]]]\n\n[[7. 消息缓冲][\n\nwebsocketpp 定义了一个消息缓冲区，通过 shared_ptr 作为参数传入，并配备了一个关联的消息管理器，该管理器允许对内存进行聚合和复用。websocketpp::message 的实现使用了 std::string 来存储有效载荷。如果接收到的消息被拆分为多个帧，那么对于每个后续帧，该字符串都可能重新分配内存。std::string 始终使用标准分配器，无法自定义分配器的选择。\n\nBeast 允许调用者指定用于接收消息或帧数据的对象，该对象可以是任何符合__DynamicBuffer__要求的类型（仿照 boost::asio::streambuf 实现）。\n\nBeast 提供了类 basic_multi_buffer，这是对 DynamicBuffer 概念的一种高效实现，它利用了多个已分配的字节数组。如果传入的消息被拆分成多个片段，则不会发生重新分配；相反，当现有分配空间填满时，会向序列中追加新的分配。Beast 不会对调用方强加任何特定的内存管理模型。Beast 提供的 basic_multi_buffer 通过模板参数支持标准分配器。您可以直接使用 Beast 自带的 DynamicBuffer，也可以根据需要自定义分配器，或者提供符合要求的自定义类型。\n\n[表格 [ [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]] [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/message_buffer/message.hpp#L78 websocketpp]] ][ [模板&lt;class DynamicBuffer&gt; 读取(DynamicBuffer&amp; dynabuf);] [模板&lt;模板&lt;class&gt; class con_msg_manager&gt; 类消息 { public: typedef lib::shared_ptr&lt;消息&gt; ptr; ... std::string m_payload; ... };] ]]]]\n\n[[8. 发送消息][\n\n发送消息时，websocketpp要求将有效载荷封装在websocketpp::message对象中，存储方式为std::string；或者，通过构造一个新的消息对象来复制调用方提供的缓冲区。消息会被放入一个待发送队列中。后台会执行异步写操作以清空该队列。无法注册任何面向用户的处理程序，以在消息或帧发送完成时获得通知。\n\nBeast 在发送数据时不会分配或复制缓冲区。调用方的缓冲区将就地发送。您可以使用任何符合__ConstBufferSequence要求的对象，从而实现高效的分散-收集 I/O 操作。\n\n[*ConstBufferSequence] 接口允许调用方从内存映射区域发送数据（在 websocketpp 中无法实现）。调用方还可使用相同的缓冲区向多个流发送数据，例如一次性将通用订阅数据广播给多个客户端。每次调用 async_write 时，完成处理程序都会在数据发送完毕后被调用一次，其调用方式与 boost::asio::async_write 完全相同。\n\n[表格 [ [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1048 Beast]] [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L672 websocketpp]] ][ [template&lt;class ConstBufferSequence&gt; void write(ConstBufferSequence const&amp; buffers);] [lib::error_code send(std::string const &amp; payload, frame::opcode::value op = frame::opcode::text); ... lib::error_code send(message_ptr msg);] ]]]]\n\n[[9. 流式消息][\n\nWebSocketpp要求整个消息必须能够完整地放入内存中，且其大小需事先已知。 \n\nBeast 允许呼叫方以单独的帧来组成消息。当数据大小事先未知，或者不希望在发送前将整个消息一次性缓冲到内存中时，这一点非常有用。例如，定期输出协程中运行的数据库查询结果；或分块发送文件内容，而无需将其全部加载到内存中。\n\n[表格 [ [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1151 Beast]] [websocketpp] ][ [template&lt;class ConstBufferSequence&gt; void write_some(bool fin, ConstBufferSequence const&amp; buffers);] [ /&lt;不可用&gt;/ ] ]]]]\n\n[[10. 流量控制][\n\nwebsocketpp 的读取实现会持续从网络异步读取数据，并将消息数据缓存起来。为防止缓存无限制增长并利用 TCP/IP 的流量控制机制，调用方可以定期关闭和重新开启这一“读取泵”。\n\n相比之下，beast::websocket::stream 不会独立启动后台活动，也不会对消息进行缓冲。它仅在调用异步初始化函数（例如 beast::websocket::stream::async_read）并附带相应处理程序时才接收数据。应用程序无需实现显式的逻辑来控制数据流。相反，它们遵循传统的模式：发出读取请求，等待读取完成，处理接收到的消息，然后再次发出读取请求，如此循环往复。\n\n[表格 [ [兽] [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L728 websocketpp]] ][ [ /&lt;隐式&gt;/ ] [lib::error_code pause_reading(); lib::error_code resume_reading();] ]]]]\n\n[[11. 连接建立][\n\nwebsocketpp 提供了 endpoint 类，该类可处理端口的绑定与监听，并创建连接对象。\n\nBeast并未在此处重新发明轮子；调用方直接使用boost::asio中已有的接口来接收传入连接、解析主机名，或建立出站连接。在套接字（或boost::asio::ssl::stream）连接成功后，便可在其基础上构造beast::websocket::stream，从而完成WebSocket握手过程。\n\nBeast 用户可自由实现自己的“连接管理器”，但并无强制要求必须这么做。\n\n[表格 [ [[@http://www.boost.org/doc/html/boost_asio/reference/async_connect.html Beast], [@http://www.boost.org/doc/html/boost_asio/reference/basic_socket_acceptor/async_accept.html 也]] [[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/endpoint.hpp#L52 websocketpp]] ][ [#include &lt;boost/asio.hpp&gt;] [template &lt;typename config&gt; class endpoint : public config::socket_type;] ]]]]\n\n[[12. WebSocket 握手][\n\n调用方可调用beast::websocket::accept来执行WebSocket握手，但并无强制要求必须使用此函数。高级用户可自行完成WebSocket握手。Beast WebSocket提供了用于构造请求或响应的工具，而Beast HTTP接口则提供了用于发送和接收HTTP/1消息的容器与算法，其中包括建立WebSocket会话所必需的HTTP Upgrade请求。 Beast 允许调用方在已接收到 HTTP 消息的情况下，将传入的 HTTP 升级请求传递出去。这种灵活性使得实现方式更加新颖且稳健。例如，一个监听套接字可以在同一端口上支持多种协议的握手过程。\n\n有时，呼叫方希望在读取WebSocket HTTP升级请求之前，先从套接字中读取一些字节。Beast允许将这些已接收的字节提供给接受函数的一个重载版本，从而实现复杂的功能。例如，一个监听套接字既可以接受常规WebSocket连接，也可以接受安全WebSocket（SSL）连接。\n\n[表格 [ [[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L501 Beast], [@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L401 同样]] [websocketpp] ][ [``` 模板 void accept(ConstBufferSequence const&amp; buffers);\ntemplate void accept(http::header&lt;true, http::basic_fields&gt; const&amp; req); ```] [ /&lt;不可用&gt;/ ] ]]]]</string>
</resources>
