19.0 Boost 基于ASIO网络编程技术

Boost ASIO库是一个基于C++语言的开源网络编程库,该库提供了成熟、高效、跨平台的网络API接口,并同时支持同步与异步两种模式,ASIO库提供了多重I/O对象、异步定时器、可执行队列、信号操作和协程等支持,使得开发者可以轻松地编写可扩展的高性能网络应用程序,同时保持代码简洁、易于维护。

在学习ASIO库之前,我们先来实现一个简单的地址解析功能,Boost库中提供了ip::tcp::resolver对象,该对象可用于解析给定主机名和端口号的IP地址,学会使用这个对象即可实现对特定主机域名地址的解析功能,如下封装实现了GetDNSAddress该函数传入一个域名,并输出该域名所对应的IP地址列表,并返回给std::vector容器内,其实现原理如下所示;

#include <iostream>
#include <vector>
#include <boost/asio.hpp>using namespace std;
using namespace boost;
using namespace boost::asio;// 传入域名解析IP地址
std::vector<std::string> GetDNSAddress(std::string hostname)
{std::vector<std::string> address_list;boost::asio::io_service ioservice;boost::asio::io_service my_io_service;boost::asio::ip::tcp::resolver resolver(my_io_service);boost::asio::ip::tcp::resolver::query query(hostname, "https");boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query);boost::asio::ip::tcp::resolver::iterator end;while (iter != end){boost::asio::ip::tcp::endpoint endpoint = *iter++;address_list.push_back(endpoint.address().to_string());}return address_list;
}

这段代码的调用很容易,只需要传入特定域名即可,如下所示代码中,我们获取www.baidu.com域名下所有的IP地址列表,并依次循环输出ref_address_list中的所有列表信息。

int main(int argc, char *argv[])
{// 从字符串产生IPip::address addr;addr = addr.from_string("192.168.1.1");if (addr.is_v4()){std::string addr_string = addr.to_string();std::cout << "IP地址: " << addr_string << std::endl;}// 根据域名获取所有DNS地址std::vector < std::string > ref_address_list;ref_address_list = GetDNSAddress("www.baidu.com");for (int x = 0; x < ref_address_list.size(); x++){std::cout << ref_address_list[x] << std::endl;}std::system("pause");return 0;
}

读者可自行编译并运行上述代码片段,当运行后会看到特定域名下所包含的所有IP信息,如下图所示;

同步TCP模式

在同步模式下,程序发起I/O操作时,调用相应的同步I/O函数将操作添加到io_service中,该请求被添加到io_service的请求队列中等待处理。然后,io_service就会不断地从队列中取出请求,并将请求传递给操作系统进行处理,直到该请求被处理完成。程序在此期间会一直处于阻塞等待的状态,直到操作完成或者因为某种原因导致操作失败。

I/O操作在操作系统完成后,操作系统会通知io_serviceio_service接收到通知后会再次进入循环,将操作结果发送回程序进行处理。程序会在此等待操作结果,并在io_service返回结果时继续执行其余代码。

同步网络通信的实现原理与原生Socket套接字通信原理保持一致,只是在ASIO模型中,需要定义一个io_service对象,在服务端环境下,我们通过ip::tcp::acceptor来指定服务端地址与端口信息,使用ip::tcp::socket创建一个套接字,通过acceptor.accept(socket)则可用于同步等待一个套接字的链接,当有新套接字连入后,我们可以使用socket.write_some函数向客户端发送一段消息。

#include <iostream>
#include <boost/asio.hpp>using namespace boost::asio;int main(int argc, char* argv[])
{io_service io;ip::tcp::acceptor acceptor(io, ip::tcp::endpoint(ip::tcp::v4(), 6666));while (1){// 创建 socket 对象ip::tcp::socket socket(io);// 等待客户端连接acceptor.accept(socket);// 显示客户端IPstd::cout << "本机地址: " << socket.local_endpoint().address() << std::endl;std::cout << "客户端地址: " << socket.remote_endpoint().address() << std::endl;// 向客户端发送 hello lysharkboost::system::error_code error;socket.write_some(buffer("hello lyshark"), error);// 如果出错,输出错误提示if (error){std::cout << boost::system::system_error(error).what() << std::endl;break;}}system("pause");return 0;
}

对于客户端而言我们可以使用tcp::endpoint创建一个链接端点,当初始化结构后就可以使用socket.connect函数连接到这个端点上,当链接被建立后,则客户端就可以使用socket.read_some函数接收服务端传递过来的消息,此处读者需要注意接受的消息需要使用boost::array存储,当接收到消息后就可以使用buffer.data()方法打印出该缓冲区内的具体内容。

#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>using namespace std;
using boost::asio::ip::tcp;int main(int argc, char* argv[])
{try{// 定义Socket对象boost::asio::io_service io;tcp::socket socket(io);// 尝试连接服务器tcp::endpoint end_point(boost::asio::ip::address::from_string("127.0.0.1"), 6666);socket.connect(end_point);while (1){boost::array<char, 1024> buffer = { 0 };boost::system::error_code error;// 接受数据并存入buffersize_t len = socket.read_some(boost::asio::buffer(buffer), error);// 判断是否出错if (error == boost::asio::error::eof)break;else if (error)throw boost::system::system_error(error);std::cout << "接收到数据: " << buffer.data() << std::endl;}}catch (std::exception& e){cout << e.what() << endl;}system("pause");return 0;
}

读者可自行编译并运行上述服务端与客户端程序,当运行后即可看到如下图所示的输出效果;

同步UDP模式

TCP和UDP是两种常见的Internet协议,TCP是一种可靠的、面向连接的协议,UDP则是不可靠的、无连接的协议。 TCP适合传输数据量大、对数据传输准确性要求高的应用,而UDP适合传输数据量小、传输速度快、对传输可靠性要求低的应用。

ASIO库在实现UDP传输时其大体思路与TCP保持一致,两者唯一的区别是在定义套接字时应使用ip::udp::命名空间,其次在传输数据方面服务端应该采用receive_from函数接收参数,如下是一段简单的UDP传输服务端实现。

#include <iostream>
#include <boost/asio.hpp>using namespace boost::asio;
using namespace boost::system;int main(int argc, char* argv[])
{io_service io;ip::udp::socket sock(io, ip::udp::endpoint(ip::udp::v4(), 6666));while (1){char buf[1];ip::udp::endpoint ep;error_code ec;// 接收参数sock.receive_from(buffer(buf), ep, 0, ec);if (ec && ec != error::message_size){throw system_error(ec);}std::cout << "发送到: " << ep.address() << std::endl;sock.send_to(buffer("hello lyshark"), ep);}system("pause");return 0;
}

接着是客户端的实现,对于UDP客户端通常采用sock.open()函数打开套接字,在打开后可调用sock.send_to向服务端发送数据,同时使用sock.receive_from接收数据包,如下是客户端代码实现。

#include <iostream>
#include <vector>
#include <boost/asio.hpp>using namespace boost::asio;
using namespace boost::system;int main(int argc, char* argv[])
{io_service io;ip::udp::endpoint send_ep(ip::address::from_string("127.0.0.1"), 6666);ip::udp::socket sock(io);sock.open(ip::udp::v4());char buf[1];// 发送数据sock.send_to(buffer(buf), send_ep);std::vector<char> v(100, 0);ip::udp::endpoint recv_ep;// 接收数据sock.receive_from(buffer(v), recv_ep);std::cout << "数据来自于: " << recv_ep.address() << std::endl;std::cout << "数据: " << &v[0] << std::endl;system("pause");return 0;
}

读者可自行编译并运行上述代码片段,则可输出如下图所示的效果;

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

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

相关文章

【Python基础】IF、Else判断以及Whlie、for循环介绍符实例

运算符 1. if 语句体验2.逻辑运算3. if 语句进阶4.While循环4.1基本语法 5.break 和 continue6. for循环 1. if 语句体验 if 判断语句基本语法 在 Python 中&#xff0c;if 语句 就是用来进行判断的&#xff0c;格式如下&#xff1a; if 要判断的条件: 条件成立时&#xff0c;…

视频一键成片是什么

视频制作过程中繁琐的步骤和高昂的成本往往成为企业迈向成功的绊脚石。美摄科技作为业界领先的视频制作技术提供商&#xff0c;针对这一痛点&#xff0c;推出了一键成片解决方案&#xff0c;旨在帮助企业快速高效地制作出优质视频内容。 美摄科技的一键成片解决方案基于先进的…

voronoi diagram(泰森多边形) 应用 - Good Manners

欢迎关注更多精彩 关注我&#xff0c;学习常用算法与数据结构&#xff0c;一题多解&#xff0c;降维打击。 voronoi 图求解点击前往 题目链接&#xff1a;https://vjudge.net/problem/URAL-1504 题目大意 有一个桌子&#xff0c;形状是圆形。 桌上放着很多蛋糕&#xff0c…

【Amazon】AWS实战 | 快速发布安全传输的静态页面

文章目录 一、实验架构图二、实验涉及的AWS服务三、实验操作步骤1. 创建S3存储桶&#xff0c;存放网站网页2. 使用ACM建立域名证书3. 设置Cloudfront&#xff0c;连接S3存储桶✴️4. 设置Route53&#xff0c;解析域名服务5. 通过CLI工具上传网页更新内容【可选】 四、实验总结 …

构建强大的Web应用之Django详解

引言&#xff1a; Django是一个功能强大且灵活的Python Web框架&#xff0c;它提供了一套完整的工具和功能&#xff0c;帮助开发者快速构建高效的Web应用。本篇文章将带您逐步了解Django的基本概念和使用方法&#xff0c;并通过实际的代码案例&#xff0c;帮助您从零开始构建自…

YOLOv8添加AIFI(Attention-based Intrascale Feature Interaction模块替换SPPF模块)

1. 引言 1.1 相关介绍 模块名称&#xff1a;Attention-based Intrascale Feature Interaction 论文名称&#xff1a;RT-DETR: DETRs Beat Yolos on Real-time Object Detection 这是论文中的图&#xff0c;此处将其中的AIFI模块拿过来改进YOLOv8。 1.2 其他可改进SPPF模块 …

SpringCloud(一) 服务架构的演变及注册RestTemplate实现服务的远程调用

目录 一, 服务架构的演变 1.1 单体架构 1.2 分布式架构 1.3 微服务 1.4 SpringCloud 二, 服务拆分和远程调用 2,1 服务拆分原则 2.2 服务拆分示例 2.3 创建相应数据库 2.4 实现远程调用示例 1, 更改需求 2, 注册RestTemplate实现远程调用 2.5 服务消费者和提供者 一…

Pinia的十个简答小案例

1. 使用Pinia进行状态管理&#xff1a; import { defineStore } from piniaexport const useCounterStore defineStore({id: counter,state: () > ({count: 0}),actions: {increment() {this.count},decrement() {this.count--}} }) 2. 在组件中使用Pinia&#xff1a; &…

Nginx搭载负载均衡及前端项目部署

目录 ​编辑 一.Nginx安装 1.安装所需依赖 2.下载并解压Nginx安装包 3.安装nginx 4.启动Nginx服务 二.Tomcat负载均衡 1.准备环境 1.1 准备两个Tomcat 1.2 修改端口号 1.3 配置Nginx服务器集群 2.效果展示 ​编辑三.前端项目打包 ​编辑四.前端项目部署 1.上传项目…

Mysql系列 -索引模型数据结构

索引就是排好序的数据结构&#xff0c;可以帮助我们快速的查找到数据&#xff0c;那么底层的数据到底是如何存储的呢&#xff1f; 为什么InnoDB 用的是Btree 存储结构&#xff1f; 大家可以看看这个可视化的网站 数据结构和算法的可视化工具 可以看到数据结构里面有链表&…

Postman接口自动化测试之——批量参数化(参数文件)

Postman接口请求中的参数引用格式&#xff1a;{{参数名}}参数文件只适用于集合中。 创建参数文件 以记事本举例&#xff0c;也可以使用其他编辑器&#xff1b;第一行参数名&#xff0c;用半角逗号&#xff08;英文逗号&#xff09;隔开&#xff0c;第二行为参数值&#xff0c…

Linux -----------------------Shell 流程判断

什么是shell Shell是操作系统的用户界面&#xff0c;负责接收和解释用户的命令&#xff0c;并将这些命令转化为操作系统内部能够理解的指令&#xff0c;然后执行相应的操作。Shell还允许用户编写脚本&#xff0c;以自动化和批处理任务&#xff0c;从而提高效率。在Linux系统中&…

100G QSFP28 BIDI LR1光模块最新解决方案

上期文章我们有介绍到100G QSFP28 BIDI ER1 Lite光模块&#xff0c;本期内容我们将继续为大家介绍100G光模块系列的100G QSFP28 BIDI LR1光模块。这款产品同样也在易天ECOC光通讯展展出&#xff0c;下面跟着小易一起来看看吧&#xff01; 易天光通信的100G QSFP28 BIDI LR1单纤…

Redis中String类型的命令

目录 Redis中的内部编码 redis的数据结构和内部编码 Redis中的String类型 String类型的常见命令 set get mget mset String类型的计数命令 incr incrby decr incrbyfloat 其他命令 append getrange setrange strlen String类型的内部编码 Redis中的内部编码…

【源码】智能导诊系统,通过患者的主诉症状,自动匹配挂号科室和医生

随着计算机技术、网络技术、医院内网、智能终端的发展成熟&#xff0c;自动化、智能化就诊将是未来医院的发展模式。在目前综合性医疗机构&#xff0c;医院建设物庞大且复杂&#xff0c;接待就诊人员数量较大&#xff0c;医院诊疗科室众多&#xff0c;就诊人员容易迷失其中&…

Vue监听事件

一、问题场景 项目有个需求&#xff0c;在登录页面&#xff0c;输入好账号密码后&#xff0c;直接可以点击回车就能够登录&#xff0c;效果和点击登录按钮一样&#xff0c;登录页面源码如下 <template><body id"poster"><el-form class"login-…

linux 下 物理迁移 mysql 数据库 不能启动问题

1、授权问题 # chown -R 777 /app/db/mysql 2、/etc/my.cnf配置问题 [mysqld] basedir/app/db/mysql datadir/app/db/mysql/data socket/app/db/mysql/mysql.sock.lock innodb_buffer_pool_size128M innodb_force_recovery 1 symbolic-links0 [mysqld_safe] log-error/app/…

嵌入式linux常用的文件传输方式

做嵌入式就避免不了移植工作&#xff0c;所谓移植就是将交叉编译生成的可执行程序&#xff0c;库&#xff0c;配置文件等传输到开发板上进行工作。 常用传输方式有以下几种&#xff1a;1.串口传输 就是使用串口传输工具rz/sz; 该工具通过串口传输在SRT串口工具…

软文推广没效果?媒介盒子分享软文优化技巧

虽然软文推广能够为企业实现品牌增值&#xff0c;但也有许多企业在推广过程中犯错导致宣传没有效果&#xff0c;今天媒介盒子就来和大家聊聊企业在进行软文推广中的常见问题以及优化技巧。 问题1&#xff1a;内容生硬无法自然融入品牌信息 这也是企业在软文写作中较常出现的问…

win7中安装node14和vue

下载并安装低版本node 13 到官网去找早期历史版本的 nodejs 13 msi格式即可&#xff0c;并一键安装&#xff0c;我安装在了 D:\Program Files\nodejs 目录下 https://nodejs.org/download/release/v13.14.0/ 下载高版本node 14 下载高版本的node zip包 https://nodejs.org/…