Boost库学习4 - 网络库asio

简介

  • asio即异步输入输出;
  • 一个跨平台的C++库,可移植;
  • 采用前摄器模式Proactor,支持以同步或异步的方式处理事件,不需要使用多线程和锁,有效避免多线程编程带来的诸多副作用(如竞争,死锁等);
  • asio官方文档

Asio基本工作流程

同步操作

  • 同步模式下,流程一步一步执行,需要上一步操作完成返回再执行下一步;
    在这里插入图片描述
  1. 你的程序Your Program通过调用I/O对象来进行操作;
  2. I/O对象将操作请求发给I/O执行上下文;
  3. I/O执行上下文调用操作系统接口来执行操作;
  4. 操作系统将操作的结果返回给I/O执行上下文;
  5. I/O执行上下文将操作结果转发给I/O对象;
  6. I/O对象将执行结果发送给你的程序;

异步操作

  • 异步模式下,由io_service提交io异步执行,程序不用等待io返回直接执行下一步;
  • 异步执行由io_service的run()函数负责检测io返回并通知预先注册的回调句柄(即回调函数),由回调句柄执行io返回的后续流程;
    在这里插入图片描述在这里插入图片描述
  1. 你的程序Your Program通过调用I/O对象来进行操作;
  2. I/O对象将请求转发给I/O执行上下文;
  3. I/O执行上下文向操作系统发出操作信号,进行异步处理,同时你的程序可以做其他事;
  4. 操作系统将异步处理结果通知到I/O执行上下文;
  5. 你的程序调用io_context::run()(或类似的io_context成员函数)检索结果;当有未完成的异步操作时,调用io_context::run()会阻塞,所以通常会在开始第一个异步操作时调用它;
  6. 在调用io_context::run()时,I/O执行上下文会将操作结果从队列中取出,然后将其传递给你的结果处理接口;

前摄器模式Proactor

在这里插入图片描述

  • 由使用者(Initiator)发起一个异步操作(Asynchronous Operation),同时创建一个异步回调对象(Completion Handler);
  • 该异步操作交给了异步操作执行器(Asynchronous Operation Processor),由它负责执行异步操作,并在完成后将一个完成事件插入完成事件队列(Completion Event Queue);
  • 前摄器(Proactor)驱动异步事件分派器(Asynchronous Event Demultiplexer)从完成事件队列中获取完成的事件(这是一个阻塞的过程),如果获取到则前摄器找出与该事件关联的回调对象并执行回调,继续后续流程;

使用条件

  • asio位于命令空间 boost::asio,使用时需要包含头文件 #include "boost/asio.hpp"

常用类和函数

boost::asio::io_service

  • I/O 服务,负责与操作系统交互,等待异步操作的结束并执行回调;
boost::asio::io_service service;
service.post(handler);  // 优先将任务排进处理队列然后返回,任务会在某个时机被完成,即handler稍后会在某个调用了service.run()的线程中被调用
service.dispatch(handler);  // 即时请求io_service去调用指定的任务
service.wrap(handler);  // 当被调用时它会调用service.dispatch(handler)
service.run();  // 监听io事件响应并执行回调

在这里插入图片描述

boost::asio::io_context

  • io对象,只有调用run方法的线程才会被asio调度去执行任务;
  • 可以看作事件循环, socket 、timer都需要它;
 boost::asio::io_context::run()  // 运行事件循环

boost::asio::ip

  • 网络通信部分

ip地址

boost::asio::ip::address(v4_or_v6_address)  //把一个v4或者v6的地址转换成ip::address
boost::asio::ip::address:from_string(str)  //根据一个IPv4地址(用.隔开的)或者一个IPv6地址(十六进制表示)创建一个地址
boost::asio::ip::address::to_string()  // 返回ip地址的字符串。
boost::asio::ip::address_v4::broadcast([addr, mask])  // 创建了一个广播地址 
boost::asio::ip::address_v4::any()   // 返回一个能表示任意地址的地址。
boost::asio::ip::address_v4::loopback() // 返回环路地址(为v4/v6协议)
boost::asio::ip::host_name()  // 用string数据类型返回当前的主机名

boost::asio::ip::address addr = boost::asio::ip::address::from_string("127.0.0.1");
boost::asio::ip::address addr = boost::asio::ip::address::from_string("www.baidu.com");

端点 endpoint

  • 表示使用某个端口连接到的一个地址;
  • 不同类型的socket有自己的endpoint类,如ip::tcp::endpoint、ip::udp::endpoint和ip::icmp::endpoint;
endpoint()  // 默认构造函数
endpoint(protocol, port)  // 创建可以接受新连接的服务器端socket
endpoint(addr, port)  // 创建一个连接到某个地址和端口的端点
ocal_endpoint()  // 返回套接字本地连接的地址
remote_endpoint() // 返回套接字连接到的远程地址

boost::asio::ip::tcp::endpoint ep1(ip::tcp::v4(), 8000);
boost::asio::ip::tcp::endpoint ep2( ip::address::from_string("127.0.0.1"), 8000);

套接字

  • asio有三种类型的套接字:ip::tcp、 ip::udp、ip::icmp,对应需要包含头文件boost/asio/ip/tcp.hpp、boost/asio/ip/udp.hpp、boost/asio/ip/icmp.hpp;
基础函数
// 分配了一个原生的socket给这个socket实例
assign(protocol,socket);

// 用给定的IP协议(v4或者v6)打开一个socket
open(protocol);

// 绑定到一个端口地址
bind(endpoint);

// 用同步的方式连接到一个端口地址
connect(endpoint);

// 用异步的方式连接到一个端口地址
async_connect(endpoint);
async_connect(endpoint, connect_handler);  // connect_handler用来处理接收连接成功消息

// 套接字是否打开
is_open();

// 关闭套接字, 任何的异步操作都会被立即关闭
close();

// 关闭套接字, 立即使send或者receive操作失效
shutdown(type_of_shutdown);

// 取消套接字上所有的异步操作
cancel();

// 示例
boost::asio::ip::tcp::endpoint ep( boost::asio::ip::address::from_string("127.0.0.1"), 8000);    // 创建端点
boost::asio::io_service service;   // 创建io服务
boost::asio::ip::tcp::socket sock(service);  // 创建套接字实例
sock.open(boost::asio::ip::tcp::v4());   //用ipv4方式打开套接字
sock.connect(ep);   //同步连接端点
sock.shutdown(ip::tcp::socket::shutdown_receive); //终止
sock.close();  //关闭
读写函数
async_receive(buffer, [flags,] handler);  // 启动从套接字异步接收数据的操作
async_read_some(buffer,handler);  // 接收一次数据, 收到多少是多少
async_read_until(stream, stream_buffer, delim, handler);  // 启动一个异步read操作, 在读取到某个分隔符时结束
async_read_until(strem, stream_buffer, completion, handler);  // 启动一个异步read操作, 由一个完成处理方法判断是否结束
async_receive_from(buffer, endpoint[, flags], handler);  // 启动从一个指定端点异步接收数据的操作
async_send(buffer [, flags], handler);  // 启动一个异步发送缓冲区数据的操作
async_write_some(buffer, handler);  // 同async_send,发送一次数据, 需要发的数据未必一次就可以发完
async_send_to(buffer, endpoint, handler);  // 启动一个异步发送缓冲区数据到指定端点的操作
receive(buffer [, flags]);  // 同步的从所给的缓冲区读取数据;在读完所有数据或者错误出现之前,这个函数都是阻塞的
receive_from(buffer, endpoint [, flags]);  //同步的从一个指定的端点获取数据并写入到给定的缓冲区;在读完所有数据或者错误出现之前,这个函数都是阻塞的
read_some(buffer);  // 同 receive(buffer)
read_until(stream, stream_buffer, delim);  // 启动一个同步read操作, 在读取到某个分隔符时结束
read_until(stream, stream_buffer, completion);  // 启动一个同步read操作, 由一个完成处理方法判断是否结束
send(buffer [, flags]);  // 同步的发送缓冲区的数据;在所有数据发送成功或者出现错误之前,这个函数都是阻塞的
send_to(buffer, endpoint [, flags]);  // 同步的把缓冲区数据发送到一个指定的端点;在所有数据发送成功或者出现错误之前,这个函数都是阻塞的
write_some(buffer);  // 同 send(buffer)
available();  // 返回有多少字节的数据可以无阻塞地进行同步读取

// 示例
boost::asio::ip::tcp::endpoint ep(ip::address::from_string("127.0.0.1"), 8000);
boost::asio::io_service service;   // 创建io服务
boost::asio::ip::tcp::socket sock(service);
sock.connect(ep);
sock.write_some(buffer("123456"));
std::cout << "size=" << sock.avaiable() << std::endl;
char buff[32];
size_t read = sock.read_some(buffer(buff));
设置查询函数
get_io_service();  // 返回构造函数中传入的io_service实例
get_option(option);  // 返回套接字的属性
set_option(option);  // 设置套接字的属性
io_control(cmd);  // 在套接字上执行一个I/O操作

接收器 acceptor

  • 对应socket API的accept()函数功能,用于服务器端,在指定的端口号接受连接,必须配合socket类才能完成通信;
boost::asio::ip::tcp::acceptor acceptor;   // 创建一个tcp接收器
acceptor.async_accept(socket, handle_accept);  // 接收连接

解析器resolver

  • 对应socket API的getaddrinfo()系列函数,用于客户端解析网址获得可用的IP地址,解析得到的IP地址可以使用socket对象连接;

boost::asio::error

  • 这个命名空间包含了调用I/O对象时返回的错误码

知识总结,交流学习,不当之处敬请指正,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值