使用Boost.asio与Boost.beast基于协程连接ws
目录
前言
本文主要介绍一个使用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的更多相关文章
- Python实现基于协程的异步爬虫
一.课程介绍 1. 课程来源 本课程核心部分来自<500 lines or less>项目,作者是来自 MongoDB 的工程师 A. Jesse Jiryu Davis 与 Python ...
- python基于协程的网络库gevent、eventlet
python网络库也有了基于协程的实现,比较著名的是 gevent.eventlet 它两之间的关系可以参照 Comparing gevent to eventlet, 本文主要简单介绍一下event ...
- lua:写了个基于协程的task调度库
写了一个(不完整的)基于协程的task调度库 sample code如下 my_spawn( function () print('f: 1') local t1 = my_spawn( functi ...
- Swoole 实战:MySQL 查询器的实现(协程连接池版)
目录 需求分析 使用示例 模块设计 UML 类图 入口 事务 连接池 连接 查询器的组装 总结 需求分析 本篇我们将通过 Swoole 实现一个自带连接池的 MySQL 查询器: 支持通过链式调用构造 ...
- 发布一个基于协程和事件循环的c++网络库
目录 介绍 使用 性能 实现 日志库 协程 协程调度 定时器 Hook RPC实现 项目地址:https://github.com/gatsbyd/melon 介绍 开发服务端程序的一个基本任务是处理 ...
- 基于协程的Python网络库gevent
import gevent def test1(): print 12 gevent.sleep(0) print 34 def test2(): print 56 gevent.sleep(0) p ...
- 分析easyswoole3.0源码,协程连接池(五)
连接池的含义,很多都知道,比如mysql的数据库连接是有限的,一开始连接mysql创建N个连接,放到一个容器里,每次有请求去容器中取出,取出用完再放回去. es3demo里,有mysql的连接池. E ...
- boost.asio与boost.log同时使用导致socket不能正常收发数据
现象: 1. 没有使用boost.log前能正常收发数据 2.加入boost.log后async_connect没有回调 fix过程: 1. gdb调试发现程序block在pthread_timed_ ...
- Go基于协程的归并排序简单实现
归并排序这个可能很多人都不知道,今天用Go语言简单的实现下,其他语言可能要基于线程来实现. //产生一个源 func ArraySource(a ...int) chan int{ out :=mak ...
- 基于ASIO的协程库orchid简介
什么是orchid? orchid是一个构建于boost库基础上的C++库,类似于python下的gevent/eventlet,为用户提供基于协程的并发模型. 什么是协程: 协程,即协作式程序,其思 ...
随机推荐
- 安装部署harbor
配置文件中修改内容hostname 和 证书 私钥 需要指定到文件 hostname: hub.rainsc.com # http related config http: # port for ht ...
- 本地部署 Overleaf 服务
️ 注意:本教程只适用于 macOS / Linux 操作系统.如果需要在 Windows 上部署 Overleaf,请先安装 WSL,之后在 WSL 中部署 Overleaf . 本地部署 Over ...
- mysql bit(1) 字段insert 报错 Data too long
insert数据时,给bit(1)字段赋值 '1' 报错 将字符串'1',修改为数字1即可
- Vue.js 异步组件传参
本文主要展示一下如何给异步组件进行参数传递: 通过 h 函数就可以啦 versions: vue@3.2.13 子组件 Async.vue <template> <div> & ...
- CSS & JS Effect – Textarea Autoresize
前言 这是一个很普遍的体验, 而且实现起来也很简单哦 参考 YouTube – How to Auto Resize Textarea using HTML CSS & JavaScript ...
- SQL Server – 树结构 (二叉树, 红黑树, B-树, B+树)
前言 很久以前有学习过各种树结构, 但后来真的没有在实际项目中运用到. 毕竟我主要负责的都是写业务代码. 太上层了 但是忘光光还是很可惜的. 所以久久可以复习一下. 记得概念也好, 帮助思考. 参考: ...
- Project: Kill e
接到上级任务,今天来暗杀 \(e\) 据说杀死 \(e\) 的方式就是把他算出来,好吧,现在我们还是来算一下 考虑使用如下代数式求解 \[e\ \text{site:baidu.com} \] 虽然我 ...
- 进程切换分析(2):TLB处理
一.前言 进程切换是一个复杂的过程,本文不准备详细描述整个进程切换的方方面面,而是关注进程切换中一个小小的知识点:TLB的处理.为了能够讲清楚这个问题,我们在第二章描述在单CPU场景下一些和TLB相关 ...
- Linux 循环设备 loop疑惑
什么是loop设备? loop设备是一种伪设备,是使用文件来模拟块设备的一种技术,文件模拟成块设备后, 就像一个磁盘或光盘一样使用.在使用之前,一个 loop 设备必须要和一个文件进行连接.这种结合方 ...
- 世界第一!华为云图引擎服务GES大幅刷新世界纪录
近日,国际关联数据基准委员会(Linked Data Benchmark Council,以下简称LDBC)公布了社交网络测试交互式负载(SNB INTERACTIVE WORKLOAD,以下简称为S ...