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

news/发布时间2024/5/18 15:48:36

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.bcls.cn/IQOx/851.shtml

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

相关文章

docker本地目录挂载

小命令 1、查看容器详情 docker inspect 容器名称 还是以nginx为例&#xff0c;上篇文章我们制作了nginx静态目录的数据卷&#xff0c;此时查看nginx容器时会展示出来&#xff08;docker inspect nginx 展示信息太多&#xff0c;这里只截图数据卷挂载信息&#xff09;&#…

FOC电流环速度环调试记录

FOC电流环速度环调试记录 电流环&#xff1a; 首先foc控制中都采用PI控制&#xff0c;没有引入微分&#xff0c;因为电流的采样率非常高不需要加入微分项&#xff1b;微分项的加入&#xff0c;会使电流采样中的高频小信号误差起到放大的作用&#xff0c;把小的误差放大&#…

C语言与C++:探索两种强大的编程语言

在编程的世界里&#xff0c;C语言和C无疑是两座重要的里程碑。它们不仅各自拥有独特的特点和优势&#xff0c;而且还在不同的领域和场景中发挥着关键作用。本文将深入探讨C语言和C的相似之处与差异&#xff0c;帮助读者更好地理解和应用这两种编程语言。 一、C语言&#xff1a…

【Linux】---Linux下基本指令(2)

目录 一、指令详细介绍1.1 cat 指令1.2 echo 指令1.3 more 指令1.4 less 指令1.5 head 指令1.6 tail 指令1.7 date 指令1.8 cal 指令1.9 find 指令1.10 grep 指令1.11 zip/unzip 指令1.12 tar 指令1.13 uname –r 指令&#xff1a; 一、指令详细介绍 1.1 cat 指令 语法&#…

论文阅读-PIM-tree:一种面向内存处理的抗偏移索引

论文名称&#xff1a;PIM-tree: A Skew-resistant Index for Processing-in-Memory 摘要 当今的内存索引性能受到内存延迟/带宽瓶颈的限制。Processing-in-memory (PIM) 是一种新兴的方法&#xff0c;可能通过实现低延迟内存访问&#xff0c;其聚合内存带宽随 PIM 节点数量扩…

IMX6ULL移植U-Boot 2022.04

目录 目录 1.编译环境以及uboot版本 2.默认编译测试 3.uboot中新增自己的开发板 3.编译测试 4.烧录测试 5.patch文件 1.编译环境以及uboot版本 宿主机Debian12u-boot版本lf_v2022.04 ; git 连接GitHub - nxp-imx/uboot-imx: i.MX U-Boot交叉编译工具gcc-arm-10.3-2021.0…

为什么从没有负值的数据中绘制的小提琴图(Violin Plot)会出现负值部分?

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 小提琴图&#xff08;Violin Plot&#xff09; 是一种用于展示和比较数据分布的可视化工具。它结合了箱形图&#xff08;Box Plot&#xff09;和密度图&#xff08;Kernel Density Plot&#xff09;的特…

centos7 arm服务器编译安装onnxruntime-gpu

前言 ONNX Runtime是适用于Linux,Windows和Mac上ONNX格式的机器学习模型的高性能推理引擎,但在arm服务器上,onnxruntime只有CPU版的,GPU版的没有,因此需要自行去编译GPU版本的才可以。 环境准备 1、python3.8 2、cmake:2.26.0版本以上,可以直接下载aarch64版本的进行…

【JavaEE】_多线程Thread类及其常用方法

目录 1. Thread类常用构造方法 2. Thread类的几个常见属性 3. 启动一个线程 4. 中断一个线程 4.1 方法1&#xff1a;手动设置标志位 4.2 方法2&#xff1a;使用Thread内置的标志位 5. 等待一个线程 6. 获取当前线程引用 7. 休眠当前线程 1. Thread类常用构造方法 方法…

MATLAB | 情人节画个花瓣venn图?

之前七夕节情人节各种花&#xff0c;相册&#xff0c;爱心啥的都快画够了&#xff0c;今年画个花瓣韦恩图&#xff1f; 花瓣上的数字是仅属于该类的样本数&#xff0c;而中心的数字是属于每一类的样本数 教程部分 0 数据准备 % 给组起名t1 t2 t3...t15 setName compose(t%d,…

视频接入协议之MIPI

MIPI&#xff08;Mobile Industry Processor Interface&#xff09;是一种用于移动设备的串行接口标准&#xff0c;旨在提供高速、低功耗、低成本的接口解决方案。MIPI联盟是一个全球性的组织&#xff0c;致力于开发、推广和管理MIPI标准。 MIPI接口包括了多种协议和规范&…

qwen1.5 chat vllm推理使用案例

参考:https://github.com/QwenLM/Qwen1.5 下载:https://huggingface.co/collections/Qwen/qwen15-65c0a2f577b1ecb76d786524 下载可以参考huggingface-cli 命令下载使用:https://blog.csdn.net/weixin_42357472/article/details/1326636931、vllm运行 显卡驱动:NVIDIA-S…

MySQL 基础知识(十)之 MySQL 架构

目录 1 MySQL 架构说明 2 连接层 3 核心业务层 3.1 查询缓存 3.2 解析器 3.3 优化器 3.4 执行器 4 存储引擎层 5 参考文档 1 MySQL 架构说明 下图是 MySQL 5.7 及其之前版本的逻辑架构示意图 MySQL 架构大致可分为以下三层&#xff1a; 连接层&#xff1a;负责跟客户…

【开源】在线办公系统 JAVA+Vue.js+SpringBoot+MySQL

目录 1 功能模块1.1 员工管理模块1.2 邮件管理模块1.3 人事档案模块1.4 公告管理模块 2 系统展示3 核心代码3.1 查询用户3.2 导入用户3.3 新增公告 4 免责声明 本文项目编号&#xff1a; T 001 。 \color{red}{本文项目编号&#xff1a;T001。} 本文项目编号&#xff1a;T001。…

HAL STM32通过multi_button库处理按键事件

HAL STM32通过multi_button库处理按键事件 &#x1f4cd;作者&#xff1a;0x1abin的multi_button库:https://github.com/0x1abin/MultiButton &#x1f4d8;MultiButton简介 MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块&#xff0c;可无限量扩展按键&#xff0c;…

SQL-Labs靶场“1-5”关通关教程

君衍. 一、准备工作二、第一关 基于GET单引号字符型注入1、源码分析2、联合查询注入过程 三、第二关 基于GET整型注入1、源码分析2、联合查询注入过程 四、第三关 基于GET单引号变形注入1、源码分析2、联合查询注入过程 五、第四关 基于GET双引号字符型注入1、源码分析2、联合查…

【RHCE】shell条件测试练习

目录 1、判断当前磁盘剩余空间是否有20G&#xff0c;如果小于20G&#xff0c;则将报警邮件发送给管理员&#xff0c;每天检查次磁盘剩余空间。 2、判断web服务是否运行 3、使用curl命令访问第二题的web服务&#xff0c;看能否正常访问&#xff0c;如果能正常访问&#xff0c;…

【Android】使用Android Studio运行Hello World项目

文章目录 1. JDK的安装与配置2. Android Studio的安装3. 运行Hello World项目3.1 新建项目3.2 修改项目配置3.2.1 修改UI界面3.2.2 配置 Android SDK 3.3 添加并运行虚拟设备3.4 运行项目 1. JDK的安装与配置 想要使用Android Studio&#xff0c;必须先配置Java环境&#xff0…

关于内存相关的梳理

1 关键字 总结 &#xff08;lowmemory&#xff0c;anr in&#xff09; 2 知识储备 虚拟机原理 垃圾回收算法 又包含标记 和清除两种算法 标记&#xff1a;程序计数器-已过时&#xff0c;可达性分析 具体可见 http://help.eclipse.org/luna/index.jsp?topic%2Forg.ec…

【AI视野·今日NLP 自然语言处理论文速览 第七十八期】Wed, 17 Jan 2024

AI视野今日CS.NLP 自然语言处理论文速览 Wed, 17 Jan 2024 (showing first 100 of 163 entries) Totally 100 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Deductive Closure Training of Language Models for Coherence, Accur…
推荐文章