之前用过libuv,异曲同工,但是c++接口很美丽。
快速入门
asio是妥协于现有c++语法的,async/await/coroutine语法糖。
某种角度上说,libuv是async/await的c语言妥协版。。。
协程概念快速入门?看下python和javascript ES6的相关sample code便清晰了!
参考官方example: https://think-async.com/Asio/asio-1.18.1/doc/
参考: https://blog.csdn.net/zhongjiezheng/article/details/44572009
executor 和 asio::execution_context
入门了官方example之后,需要学习一个新概念 Executor
参考 https://blog.csdn.net/qq_35976351/article/details/106959768 讲的不错
- Executor 是接口 是一群function (数据访问函数visitor)
- Execution_context 是数据库 (变量存储storage)
ASIO把executor设计成 数据访问函数(visitor) 与 变量存储(storage) 分离,也就是一个 变量存储(storage) 可以有许多条路(getter/setter)访问,这些不同的路就是多种Executor。
带着这个概念来看下:https://zhuanlan.zhihu.com/p/87400227
完整代码:https://wkkkkk.github.io/2019/06/26/a-priority-queue-with-boost-asio/priority_handler_queue.cpp
补充解释上述代码:
- class executor叫什么名字无所谓,也可以叫myexecutor,只要他内部含有一些成员函数例如post(), defer()等等,就是Executor,也就是官方文档中的 "Conformance to the executor concept."
- 定义 context 只需 inherit from asio::execution_context,常用的io_context也是继承于他的
那strand是什么
重看下这个例子:https://think-async.com/Asio/asio-1.18.1/doc/asio/tutorial/tuttimer5.html
The strand class template is an executor adapter that guarantees that,
for those handlers that are dispatched through it, an executing
handler will be allowed to complete before the next one is started.
官方文档里说他是基于executor的壳(adapter),我们想给executor推任务,则通过strand这个adapter,再由它转给executor。
c++中 ->template
是什么
参照 C++ 为什么有时候必须额外写 template? - 廖统浪的回答 - 知乎
https://www.zhihu.com/question/37990298/answer/78820977
为了消除歧义,避免<>被识别成大于小于号
Service 是什么,以及有何意义
先阅读源码中 src/examples/cpp03/services/ 这个例子,然后再看:
https://stackoverflow.com/questions/23887056/trying-to-understand-boost-asio-custom-service-implementation
- service可以理解成 execution_context下面的一个模块,它的所有权、生命周期由execution_context控制。
- 因此他的new是在execution_context里面asio的代码做的
- 上述链接里讲到:我们期望service不阻塞用户io_context,在后台默默无声的做完事情后提示给用户 io_context,所以样例代码里会开线程。系统异步调用同理,后台默默无声做完是内核线程干的事。。
好用的asio::streambuf 和 asio::buffer
先看 https://www.cnblogs.com/my_life/articles/4892557.html
再看 https://izualzhy.cn/stream-buffer
简述asio::streambuf
一个大容器,里面有两块连续区域:写区域和读区域
.prepare(X)
在 写区域的尾部 申请 X bytes 的内存.commit(Y)
将 写区域的头部 的 Y bytes 移到读区域.data()
获取 读区域的头部.consume(Z)
将 读区域头部 的 Z bytes Drop掉
那asio::buffer是?
- 是一个wrapper of
- 不持有数据,只存储数据指针(而asio::streambuf是内部有存储区域的)
- 官方文档中说
interface asio::buffer
分为const_buffer和mutable_buffer两种,顾名思义,但这两种内部都不存储数据,只存指针
在asio::read_some
里面用?
asio::streambuf rdbuf;
asio::async_read_some(rdbuf.prepare(32), [](auto ec, auto len){});
asio TCP相关周期
- 由 asio::acceptor 创建socket
- 在
async_acceptor(callback)
等待过程中,调用acceptor.close()
,则在callback中会收到`
error_code{125, Operation aborted} - 建立连接后
tcp::socket.shutdown(RECEIVE)
后,async_read(callback)
会收到error_code{2, End of file}
- 建立连接后
tcp::socket.shutdown(SEND)
后,使用async_write(callback)
会收到error_code{32, Broken pipe}
- 建立连接后 直接使用
tcp::socket.close()
则之后,async_read(callback)
会收到error_code{125, Operation aborted}
为什么没有co Routine的await async介绍?
截至目前,首先各大编译器支持有限(即使是最新版),而且配置环境也浪费时间。。搞工程嘛,要想着赚钱,时间就是金钱!
还有就是lambda满天飞实在是好用(如果支持lambda template就更好了)