第13章 网络 Page741~744 asio核心类 ip::tcp::socket

1.   ip::tcp::socket

liburl库使用"curl*" 代表socket 句柄
asio库使用ip::tcp::socket类代表TCP协议下的socket对象。

将“句柄”换成“对象”,因为asio库是不打折扣的C++库

ip::tcp::socket提供一下常用异步操作都以async开头

表13-3 tcp::socket提供的异步操作
async_connect()Start an asynchronous connect
async_read_some()Start an asynchronous read
async_wrtie_some()Start an asynchronous write

对应的注释以“Start...”开始,表明一个异步操作函数只是负责开始一件事,并不一直等到这件事情完成。

async_connect() : 主动发起一个连接请求

async_read_some() : 从该网络读一些数据,即有多少读多少

async_wrtie_some() : 向该网络写一些数据,即能写多少写多少

网络数据的传输,无论是发是收,是块是慢,相比CPU的计算速度,总是可以认为数据是在“断断续续”地流动的。

在libcurl下载新浪和搜狐网站的例子说明中,我们已经有关相关描述。带“_some”后缀的读写操作,正是用于实现“有多少处理多少”的思路。

不过,也会有许多时候程序明确知道需要读入或写出多少字节。asio提供一对自由函数,用于处理这种情况,如表13-4所列

表13-4 明确字节数的异步读写自由函数
async_read()Start an asynchronous read
async_write()Start an asynchronous write

【小提示】:“读/写”还是“接受/发送”

asio::ip::tcp:;socket也提供receive()和send()方法。入参的功能与read_some()和write_some()一样。细微差异是“receive()/send()”有另一套较少使用的重载版本。

既然是异步操作,就和C++的async()方法类似,调用时需要传入一个动作,用于在操作完成时回调,不管是读操作还是写操作,它们都需要这样一个原型的操作:

void handler(/*原型的名字无所谓*/const boost::system::error_code& error, std::size_t bytes_transferred
);

如果操作发生错误,error传入出错信息,这一点和定时器的回到操作的入参一样,其实是asio中各类回调都必须有的入参。如果操作成功,第二个入参表示本次读到或者写出多少字节。

【课堂作业】: 对比libcurl和asio网络读写回调

复习libcurl设置CURLOPT_READFUNCTION、CURLOPT_WRITEFUNCTION时所使用的原型,并与asio作对比。

作业的答案必须包含一点:libcurl所需回调用的函数带有数据,比如当读到网页数据时,libcurl回调我们设定的函数是:

size_t write_html(char* data, size_t size, size_t nmemb, void*);

第一个入参就是“char* data”就是libcurl读到的数据,通过回到交给我们处理,上例中我们将它写成一个磁盘文件;

但asio版本的回调,两个入参,一个出错时才有用,另一个只是告诉我们数据的大小。可是我们更关心的是数据呀,特别是读操作。

异步读操作:

让我们从最关心的读操作看起。成员函数async_read_some()的原型如下:

template <typename MutableBufferSequence, typename ReadHandler>
void async_read_some(const MutableBufferSequence& buffers, ReadHandler handler);

 忽略模版,先看简化版:

void async_read_some(buffers, handler);

第一个入参要一个“内存块”对象,第二个入参就是前面说的handler()回调操作,可以是函数指针、可以是……

buffers的类型虽然是模版,但类型模版名称MutableBuffer透露端倪,它暗示我们这块buffers应该是“Mutable可变的”。在asio中,“可变的”内存块对象既表示其内容可被修改,也表示万一空间不足,该内存块对象还应支持扩张容量。简单滴说就是类似std::vector类型的对象。这样的要求非常合理,因为read some正意味着事先不确定这次到底能读到多少字节的数据。

用于明确读取指定字节内容的自由函数async_read()简化原型如下:

void async_read(ip::tcp::socket& socket,, const MutableBufferSequence& buffers, ReadHandler handler);

多出第一个入参,指定负责异步读的网络底层套接字socket;
重点是内部实现的读取数据过程,会反复地读取直到buffers填满或读操作出错为止。

异步写操作

async_write_some()原型如下:

template <typename ConstBufferSequequence, typename WriteHandler>
void async_write_some(const ConstBufferSequequence& buffers, WriteHandler handler);

ConstBufferSequequence表明,这次要的buffer不会被修改。因为待写的数据肯定得事先准备好,
有多大,有什么内容一切都是定的。

可见对于网络读写操作所需的数据存储,asio要求用户方在发起异步操作前就自行准备好(上述入参buffers)。asio通常将直接使用该内存;libucurl则是由库创建内存,要求我们在回调操作时读出或写入。

asio的策略易用性较差,因为用户需要在异步操作发起到完成之间维护好这块内存;但性能较好,
因为减少内存复制或内存申请的次数。

用于明确写出指定字节内容的自由函数async_write()简化原型如下:

void async_write(ip::tcp::socket& socket, const ConstBufferSequequence& buffers, WriteHandler handler);

第一个入参用于指定负责异步读的网络底层套接字。内部实现的写数据过程,会负责将buffers内部的数据全部写出或操作出错为止。

异步发起连接。

async_connect()的原型为

template <typename ConnectHandler>
void async_connect(const endpoint_type& peer_endpoint, ConnectHandler handler);

入参peer_endpoint是待连接的目标地址,其数据结构留到下一小节讲解。
入参handler是连接操作完成(失败或成功)后续回调的操作。连接操作不需要显式数据传递,
因此和定时器回调一样,只有error入参:

void handler(const boost::system::error_code& error);

拥有async_connect异步连接,async_read_some异步读,和async_write_some异步写的方法,
如果我们有一个ip::tcp::socket对象,就可以将连接,读,写串成异步操作链。

应用代码,io_service以及操作系统(OS)三者共同串成的,异步操作链示意图如图13-20所示:

除连接操作只需一次之外,后续的读写曹组可以根据需要各种组合。比如图中示意一写一读,实际应用也有可能是“写,写,读,读”或“读,读,写,写”。在后面“echo通信示例”,我们给出链式异步操作的实现代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/688093.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[嵌入式系统-28]:开源的虚拟机监视器和仿真器:QEMU(Quick EMUlator)与VirtualBox、VMware Workstation的比较

目录 一、QEMU概述 1.1 QEMU架构 1.2 QEMU概述 1.3 什么时候需要QEMU 1.4 QEMU两种操作模式 1.5 QEMU模拟多种CPU架构 二、QEMU与其他虚拟机的比较 2.1 常见的虚拟化技术 2.1 Linux KVM 2.2 Windows VirtualBox 2.3 Windows VMware workstation 三、VirtualBox、VM…

Vue22 Vue监测数据改变的原理_数组

实例 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>Vue监测数据改变的原理_数组</title><!-- 引入Vue --><script type"text/javascript" src"../js/vue.js"></script>&…

fish终端下conda activate失败

【问题】fish终端下激活conda环境报错&#xff1a; >> conda activate base CondaError: Run conda init before conda activate ## 然而运行 conda init fish 仍旧无法解决【解决】 参考&#xff1a;https://github.com/conda/conda/issues/11079 方法一&#xf…

2024.02.18作业

1. 使用fgets统计给定文件的行数 #include <stdio.h> #include <stdlib.h> #include <string.h>int main(int argc, char const *argv[]) {if (argc ! 2){puts("input file error");puts("usage:./a.out filename");return -1;}FILE* f…

CSP-201812-1-小明上学

CSP-201812-1-小明上学 解题思路 #include <iostream> using namespace std; int main() {int red, yellow, green, n, timeSum 0;cin >> red >> yellow >> green;cin >> n;for (int i 0; i < n; i){int flag, time;cin >> flag &g…

分享视频二维码如何生成?怎么让其他人扫码查看自己的视频?

现在很多展示性的视频都会通过生成二维码的方式来传播分享&#xff0c;选择二维码的方式来分享能够更加快捷的获取视频内容&#xff0c;让更多人可以同时查看&#xff0c;有效提高视频传播的速度和效率。那么怎么制作视频二维码呢&#xff1f;其实方法很简单&#xff0c;只需要…

lvs DR模式+基于五台服务器部署keepalived + lvs DR模式架构(前端带路由)负载均衡的高可用集群

lvs DR模式基于五台服务器部署keepalived lvs DR模式架构(前端带路由)负载均衡的高可用集群 DR模式一&#xff1a; 客户端&#xff1a;172.20.26.167 LVS服务器&#xff1a;172.20.26.198 后端服务器&#xff1a;172.20.26.218 后端服务器&#xff1a;172.20.26.210 两台…

三勾点餐系统源码,java后台+微信小程序 实现完整的餐厅点餐

三勾点餐系统基于javaspringbootelement-plusuniapp打造的面向开发的小程序商城&#xff0c;方便二次开发或直接使用&#xff0c;可发布到多端&#xff0c;包括微信小程序、微信公众号、QQ小程序、支付宝小程序、字节跳动小程序、百度小程序、android端、ios端。 功能介绍 1.…

【牛客面试必刷TOP101】Day23.BM27 按之字形顺序打印二叉树和BM30 二叉搜索树与双向链表

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;牛客面试必刷TOP101 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&…

在字节划水的7年,太真实了。。

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 测试这条路是坎坷的&#xff0c;我自己深有体会。 我们的起点低…

力扣题目训练(15)

2024年2月8日力扣题目训练 2024年2月8日力扣题目训练507. 完美数520. 检测大写字母521. 最长特殊序列 Ⅰ221. 最大正方形237. 删除链表中的节点115. 不同的子序列 2024年2月8日力扣题目训练 2024年2月8日第十五天编程训练&#xff0c;今天主要是进行一些题训练&#xff0c;包括…

ViT: transformer在图像领域的应用

文章目录 1. 概要2. 方法3. 实验3.1 Compare with SOTA3.2 PRE-TRAINING DATA REQUIREMENTS3.3 SCALING STUDY3.4 自监督学习 4. 总结参考 论文&#xff1a; An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale 代码&#xff1a;https://github.com…

Python爬虫详解(一看就懂)

爬虫 爬虫是什么 爬虫简单的来说就是用程序获取网络上数据这个过程的一种名称。 爬虫的原理 如果要获取网络上数据&#xff0c;我们要给爬虫一个网址&#xff08;程序中通常叫URL&#xff09;&#xff0c;爬虫发送一个HTTP请求给目标网页的服务器&#xff0c;服务器返回数据…

机器学习---规则学习(序贯覆盖、单条规则学习、剪枝优化)

1. 序贯覆盖 回归&#xff1a; 分类&#xff1a; 聚类&#xff1a; 逻辑规则&#xff1a; 读作&#xff1a;若&#xff08;文字1且文字2且...&#xff09;&#xff0c;则目标概念成立 规则集&#xff1a;充分性与必要性&#xff1b;冲突消解&#xff1a;顺序规则、缺省规则…

nacos 2.3.1-SNAPSHOT 源码springboot方式启动(详细)附改造工程地址

文章时间是2024-2-18日&#xff0c;nacos默认develop分支&#xff0c;最新版是2.3.1-SNAPSHOT版本。 我们这里就以nacos最新版进行改造成springboot启动方式。 1. Clone 代码 nacos github地址&#xff1a;https://github.com/alibaba/nacos.git 根据上面git地址把源码克隆到…

[ai笔记10] 关于sora火爆的反思

欢迎来到文思源想的ai空间&#xff0c;这是技术老兵重学ai以及成长思考的第10篇分享&#xff01; 最近sora还持续在技术圈、博客、抖音发酵&#xff0c;许多人都在纷纷发表对它的看法&#xff0c;这是一个既让人惊喜也感到焦虑的事件。openai从2023年开始&#xff0c;每隔几个…

c++中浮点类型比较的理解

为什么浮点类型存在误差 带有小数的表示&#xff1a; 25.3 整数通过除2取余法表示&#xff1a; 25/2…1 12/2…0 6/2…0 3/2…1 1/2…1 倒过来&#xff1a;25&#xff08;十进制&#xff09; 11001&#xff08;二进制&#xff09; 小数部分通过乘2取整法&#xff1a; 0.3 * 2 …

wps快速生成目录及页码设置(自备)

目录 第一步目录整理 标题格式设置 插入页码&#xff08;罗马和数字&#xff09; 目录生成&#xff08;从罗马尾页开始&#xff09; ​编辑目录格式修改 第一步目录整理 1罗马标题 2罗马标题1一级标题 1.1 二级标题 1.2二级标题2一级标题 2.1 二级标题 2.2二级标题3一级标…

VMWare ubuntu共享宿主机window11文件夹

宿主机window的设置 找到需要共享的文件夹&#xff0c;比如我需要share文件夹共享到虚拟机中 点击“共享”文件夹属性&#xff0c;如果找不到“共享”选项卡&#xff0c;需要在下面的“选项”中 注意勾选“使用共享向导&#xff08;推荐&#xff09;”&#xff0c;如果已经勾…

notepad++打开文本文件乱码的解决办法

目录 第一步 在编码菜单栏下选择GB2312中文。如果已经选了忽略这一步 第二步 点击编码&#xff0c;红框圈出来的一个个试。我切换到UTF-8编码就正常了。 乱码如图。下面分享我的解决办法 第一步 在编码菜单栏下选择GB2312中文。如果已经选了忽略这一步 第二步 点击编码&#…