Boost WebSocket 学习

一、Asio

Boost 的 WebSocket 是基于 Boost 的异步 IO 库 Asio。Boost.Asio 是使用现代 C++ 技术为网络和 I/O 异步编程模型而做的库。

1、异步操作

异步操作表示在后台启动和执行的工作,而启动该工作的用户代码可以继续处理其他事情。initiating function 是一个可以由用户调用来启动异步操作的函数。一个 completion handler 是一个用户提供的,只允许移动的函数对象,它将被调用最多一次,在异步操作完成时被调用并以异步操作的结果为参数。

2、异步代理

异步代理是异步操作的顺序组合。每个异步操作都被认为是异步代理的一部分,即使该代理只包含单个操作。异步代理是可以与其他代理并发执行工作的实体。异步代理与异步操作的关系就像线程与同步操作的关系一样。 

异步代理具有相关的特征,这些特征指定异步操作在组成该代理时应该如何表现,例如:

  • Allocator,它决定代理的异步操作如何获取内存资源。
  • Cancellation slot,它决定代理的异步操作如何支持取消。
  • Executor,它决定代理的 completion handler 将如何排队和运行。

3、线程和 Boost.Asio

io_context 是线程安全的。

多个线程可以调用 io_context::run() 来建立一个线程池,其中可以调用 completion handler。所有加入 io_context 池的线程都被认为是相同的,io_context 可以以任意的方式在它们之间分配工作。

io_context 构造函数允许程序指定并发提示。这是对 io_context 实现关于应该用于运行 completion handler 的活动线程数量的建议。

4、Strands:使用线程不需要显示锁

一个 strand 被定义为事件处理程序的严格顺序调用(即没有并发调用)。使用 strand 允许在多线程程序中执行代码,而不需要显式锁定(例如使用互斥锁)。

链可以是隐式的,也可以是显式的,例如:

  • 仅从一个线程调用 io_context::run() 意味着所有事件处理程序都在隐式链中执行,因为 io_context 保证处理程序只能从 run() 内部调用。
  • 在与一个连接相关联的异步操作的单链中(例如,在像 HTTP 这样的半双工协议实现中),处理程序不可能并发执行。这是一条隐式链。
  • 显式的 strand 是 strand<> 或 io_context::strand 的实例。所有事件处理函数对象都需要使用 boost::asio::bind_executor() 绑定到 strand 上,或者通过 strand 对象 posted/dispatched。

所有异步操作都通过使用 get_associated_executor 函数获得处理程序的关联 executor。例如:

boost::asio::associated_executor_t<Handler> a = boost::asio::get_associated_executor(h);

boost::asio::bind_executor() 函数是用于将特定的 executor 对象(比如一个 strand)绑定到一个completion handler。此绑定自动关联 executor:

my_socket.async_read_some(my_buffer,
    boost::asio::bind_executor(my_strand,
      [](error_code ec, size_t length)
      {
        // ...
      }));

5、协程

spawn() 函数是用于运行 stackful coroutines 的高级包装器。spawn() 函数使程序能够以同步的方式实现异步逻辑,如下例所示:

boost::asio::spawn(my_strand, do_echo, boost::asio::detached);

// ...

void do_echo(boost::asio::yield_context yield)
{
  try
  {
    char data[128];
    for (;;)
    {
      std::size_t length =
        my_socket.async_read_some(
          boost::asio::buffer(data), yield);

      boost::asio::async_write(my_socket,
          boost::asio::buffer(data, length), yield);
    }
  }
  catch (std::exception& e)
  {
    // ...
  }
}

第一个参数可以是 executor 或 execution context。此参数确定允许协程执行的 context。

第二个参数是一个函数对象:

void coroutine(boost::asio::yield_context yield);

它指定要作为协程的一部分运行的代码。参数 yield 可以传递给异步操作来代替 completion handler。这将启动异步操作并挂起协程。当异步操作完成时,协程将自动恢复。

要从操作中收集 error_code,而不是让它抛出异常,请将输出变量与 yield_context 关联如下:

boost::system::error_code ec;
std::size_t length =
  my_socket.async_read_some(
    boost::asio::buffer(data), yield[ec]);

二、Boost.Beast.WebSocket

WebSocket 连接需要一个有状态对象,在 Beast 中由一个类模板 WebSocket::stream 表示。接口使用分层流模型。websocket 流对象包含另一个流对象,称为“next layer”,用于执行I/O。各模板参数说明如下:

namespace boost {
namespace beast {
namespace websocket {

template<
    class NextLayer,
    bool deflateSupported = true>
class stream;

} // websocket
} // beast
} // boost

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值