目录

前言

本文主要介绍一个使用Boost.asio和Boost.beast基于协程连接Websocket(ws)的方法。其中C++版本为20,Boost版本为1.82。

准备工作

首先需要构造一个最基本的ws服务器用于测试。

本文使用nodejs构造了一个简单的ws服务器,基于ws库。

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function connection(ws) {
console.log('New client connected')
ws.on('message', function incoming(message) {
console.log('received: %s', message);
ws.send(message);
});
}); console.log('WebSocket server is running on port 8080');

实现

初始化io_context并监听信号

boost::asio::io_context io_context;
boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
signals.async_wait([&](auto, auto){ io_context.stop(); });

启动连接ws的线程并启动io_context

boost::asio::co_spawn(io_context, ws, boost::asio::detached);
io_context.run();

其中ws的签名为boost::asio::awaitable<void> ws()

建立tcp链接(以下步骤皆位于ws函数中)

这一步可以分为两个步骤,解析dns以及建立tcp链接。

auto executor = co_await boost::asio::this_coro::executor;
boost::asio::ip::tcp::socket socket(executor);
boost::asio::ip::tcp::resolver resolver(executor); // 如果不使用dns解析,也可以直接使用以下直接代替
// boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string("127.0.0.1"), 8080)
auto point = co_await resolver.async_resolve("localhost", "8080", boost::asio::use_awaitable); co_await socket.async_connect(
point->endpoint(),
boost::asio::use_awaitable);

ws握手

先使用boost::beast::websocket::stream<boost::asio::ip::tcp::socket&>包装,然后进行握手。

boost::beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(socket);
co_await ws.async_handshake("127.0.0.1", "/", boost::asio::use_awaitable);

握手过程中发送的信息类似于

GET / HTTP/1.1
Host: www.example.com
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Key: 2pGeTR0DsE4dfZs2pH+8MA==
Sec-WebSocket-Version: 13
User-Agent: Boost.Beast/216

传输数据

boost::asio::steady_timer timer(executor);
for (;;) {
co_await ws.async_write(boost::asio::buffer("hello"), boost::asio::use_awaitable);
std::cout << "send: hello" << std::endl; boost::beast::flat_buffer buffer;
co_await ws.async_read(buffer, boost::asio::use_awaitable);
std::cout << boost::format("recv: %s") % std::string((char *)buffer.data().data(), buffer.data().size()) << std::endl; timer.expires_after(std::chrono::seconds(1));
co_await timer.async_wait(boost::asio::use_awaitable);
}

效果

总结

有了协程之后,boost感觉好用多了

使用Boost.asio与Boost.beast基于协程连接ws的更多相关文章

  1. Python实现基于协程的异步爬虫

    一.课程介绍 1. 课程来源 本课程核心部分来自<500 lines or less>项目,作者是来自 MongoDB 的工程师 A. Jesse Jiryu Davis 与 Python ...

  2. python基于协程的网络库gevent、eventlet

    python网络库也有了基于协程的实现,比较著名的是 gevent.eventlet 它两之间的关系可以参照 Comparing gevent to eventlet, 本文主要简单介绍一下event ...

  3. lua:写了个基于协程的task调度库

    写了一个(不完整的)基于协程的task调度库 sample code如下 my_spawn( function () print('f: 1') local t1 = my_spawn( functi ...

  4. Swoole 实战:MySQL 查询器的实现(协程连接池版)

    目录 需求分析 使用示例 模块设计 UML 类图 入口 事务 连接池 连接 查询器的组装 总结 需求分析 本篇我们将通过 Swoole 实现一个自带连接池的 MySQL 查询器: 支持通过链式调用构造 ...

  5. 发布一个基于协程和事件循环的c++网络库

    目录 介绍 使用 性能 实现 日志库 协程 协程调度 定时器 Hook RPC实现 项目地址:https://github.com/gatsbyd/melon 介绍 开发服务端程序的一个基本任务是处理 ...

  6. 基于协程的Python网络库gevent

    import gevent def test1(): print 12 gevent.sleep(0) print 34 def test2(): print 56 gevent.sleep(0) p ...

  7. 分析easyswoole3.0源码,协程连接池(五)

    连接池的含义,很多都知道,比如mysql的数据库连接是有限的,一开始连接mysql创建N个连接,放到一个容器里,每次有请求去容器中取出,取出用完再放回去. es3demo里,有mysql的连接池. E ...

  8. boost.asio与boost.log同时使用导致socket不能正常收发数据

    现象: 1. 没有使用boost.log前能正常收发数据 2.加入boost.log后async_connect没有回调 fix过程: 1. gdb调试发现程序block在pthread_timed_ ...

  9. Go基于协程的归并排序简单实现

    归并排序这个可能很多人都不知道,今天用Go语言简单的实现下,其他语言可能要基于线程来实现. //产生一个源 func ArraySource(a ...int) chan int{ out :=mak ...

  10. 基于ASIO的协程库orchid简介

    什么是orchid? orchid是一个构建于boost库基础上的C++库,类似于python下的gevent/eventlet,为用户提供基于协程的并发模型. 什么是协程: 协程,即协作式程序,其思 ...

随机推荐

  1. 安装部署harbor

    配置文件中修改内容hostname 和 证书 私钥 需要指定到文件 hostname: hub.rainsc.com # http related config http: # port for ht ...

  2. 本地部署 Overleaf 服务

    ️ 注意:本教程只适用于 macOS / Linux 操作系统.如果需要在 Windows 上部署 Overleaf,请先安装 WSL,之后在 WSL 中部署 Overleaf . 本地部署 Over ...

  3. mysql bit(1) 字段insert 报错 Data too long

    insert数据时,给bit(1)字段赋值 '1' 报错 将字符串'1',修改为数字1即可

  4. Vue.js 异步组件传参

    本文主要展示一下如何给异步组件进行参数传递: 通过 h 函数就可以啦 versions: vue@3.2.13 子组件 Async.vue <template> <div> & ...

  5. CSS & JS Effect – Textarea Autoresize

    前言 这是一个很普遍的体验, 而且实现起来也很简单哦 参考 YouTube – How to Auto Resize Textarea using HTML CSS & JavaScript ...

  6. SQL Server – 树结构 (二叉树, 红黑树, B-树, B+树)

    前言 很久以前有学习过各种树结构, 但后来真的没有在实际项目中运用到. 毕竟我主要负责的都是写业务代码. 太上层了 但是忘光光还是很可惜的. 所以久久可以复习一下. 记得概念也好, 帮助思考. 参考: ...

  7. Project: Kill e

    接到上级任务,今天来暗杀 \(e\) 据说杀死 \(e\) 的方式就是把他算出来,好吧,现在我们还是来算一下 考虑使用如下代数式求解 \[e\ \text{site:baidu.com} \] 虽然我 ...

  8. 进程切换分析(2):TLB处理

    一.前言 进程切换是一个复杂的过程,本文不准备详细描述整个进程切换的方方面面,而是关注进程切换中一个小小的知识点:TLB的处理.为了能够讲清楚这个问题,我们在第二章描述在单CPU场景下一些和TLB相关 ...

  9. Linux 循环设备 loop疑惑

    什么是loop设备? loop设备是一种伪设备,是使用文件来模拟块设备的一种技术,文件模拟成块设备后, 就像一个磁盘或光盘一样使用.在使用之前,一个 loop 设备必须要和一个文件进行连接.这种结合方 ...

  10. 世界第一!华为云图引擎服务GES大幅刷新世界纪录

    近日,国际关联数据基准委员会(Linked Data Benchmark Council,以下简称LDBC)公布了社交网络测试交互式负载(SNB INTERACTIVE WORKLOAD,以下简称为S ...