目录

前言

本文主要介绍一个使用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. 使用Istio服务网格进行微服务网络治理

    在Rainbond中,用户可以对不同的应用设置不同的治理模式,即用户可以通过切换应用的治理模式,来按需治理应用,这样带来的好处便是用户可以不被某一个ServiceMesh框架所绑定,且可以快速试错,能 ...

  2. stm32学习之调试篇踩坑记录

    如何下载fml文件 找不到64k的fml文件 could not stop cortex-m device:无法连接,我当时是在程序中的一些初始化函数中,有几条语句禁用了(JTAG+SW) 接线顺序, ...

  3. 2024 NepCTF

    NepCTF NepMagic -- CheckIn 直接玩游戏就能出 注意有一关要把隐藏的方块全找到 NepCamera 先使用tshark读取数据 结果文件中发现大量jpeg头ffd8ffe0. ...

  4. 关于安装李沐深度学习d2l包报错的解决办法(保姆教程)

    目录 目录:d2l包安装失败的解决过程 前言 一.李沐提供的安装方式 1. 创建一个新的环境 2. 激活 d2l 环境 3. 安装深度学习框架和d2l软件包 3.1 安装PyTorch的CPU或GPU ...

  5. 利用水墨映客图床作为COS服务器

    目录 利用水墨映客作为COS服务器 利用picGo配合typora上传图片 安装PicGo(以Windows为例) 安装lankong插件 在SpringBoot中开发图片上传工具类 设置图片上传请求 ...

  6. sentinel中如何使用@SentinelResource和openFeign来进行服务熔断和降级的操作

    sentinel 前方参考 计算QPS-Sentinel限流算法 https://www.cnblogs.com/yizhiamumu/p/16819497.html Sentinel 介绍与下载使用 ...

  7. vue3 modifier

    vue3 modifier 是什么? modifier 中文意思为修饰符. 在vue3中主要是体现在v-model上,vue3允许我们添加自定义修饰符. 比如说这样: <template> ...

  8. git 回退之前某次提交

    git 版本回退,用于误提交或者版本回退 一.回滚到之前的某次版本,且该版本后的提交都不要(用于版本回退) 1).首先查看版本号,用 git log 命令查看要回退的版本对应的commit Id co ...

  9. 为什么Java已经不推荐使用Stack了?

    为什么不推荐使用Stack Java已不推荐使用Stack,而是推荐使用更高效的ArrayDeque 为什么不推荐使用 性能低:是因为 Stack 继承自 Vector, 而 Vector 在每个方法 ...

  10. CSS & JS Effect – Hero Banner Swiper

    效果 重点 1. 一张图片, 一个 content 定位居中作为一个 slide 2. slider 用了 JavaScript Library – Swiper 3. 当 slide active ...