19.0 Boost 基于ASIO网络编程技术

2023-10-31 09:44

本文主要是介绍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;
}

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

这篇关于19.0 Boost 基于ASIO网络编程技术的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/314467

相关文章

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

Linux网络配置之网桥和虚拟网络的配置指南

《Linux网络配置之网桥和虚拟网络的配置指南》这篇文章主要为大家详细介绍了Linux中配置网桥和虚拟网络的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、网桥的配置在linux系统中配置一个新的网桥主要涉及以下几个步骤:1.为yum仓库做准备,安装组件epel-re

python如何下载网络文件到本地指定文件夹

《python如何下载网络文件到本地指定文件夹》这篇文章主要为大家详细介绍了python如何实现下载网络文件到本地指定文件夹,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下...  在python中下载文件到本地指定文件夹可以通过以下步骤实现,使用requests库处理HTTP请求,并结合o

Linux高并发场景下的网络参数调优实战指南

《Linux高并发场景下的网络参数调优实战指南》在高并发网络服务场景中,Linux内核的默认网络参数往往无法满足需求,导致性能瓶颈、连接超时甚至服务崩溃,本文基于真实案例分析,从参数解读、问题诊断到优... 目录一、问题背景:当并发连接遇上性能瓶颈1.1 案例环境1.2 初始参数分析二、深度诊断:连接状态与

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

SpringBoot使用OkHttp完成高效网络请求详解

《SpringBoot使用OkHttp完成高效网络请求详解》OkHttp是一个高效的HTTP客户端,支持同步和异步请求,且具备自动处理cookie、缓存和连接池等高级功能,下面我们来看看SpringB... 目录一、OkHttp 简介二、在 Spring Boot 中集成 OkHttp三、封装 OkHttp

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用