5、boost库使用asio 您所在的位置:网站首页 polling模式 5、boost库使用asio

5、boost库使用asio

2023-02-24 21:40| 来源: 网络整理| 查看: 265

  asio库基于操作系统提供的异步机制,采用前摄器模式(Proactor)实现可移植的异步(或同步)IO操作,不需要使用多线程和锁,有效避免多线程编程带来的诸多有害副作用(如竞争,死锁)。

  asio封装了操作系统的select、kqueue、poll/epoll、overlapped I/O等机制,实现异步IO模型。在同步模式下,程序发起一个IO操作,向io_service提交请求,io_service把操作转交给操作系统,同步地等待。当IO操作完成时,操作系统通知io_service,然后io_service再把结果发回给程序,完成整个同步流程。在异步模式下,程序除了要发起IO操作,还要定义一个用于回调的完成处理函数。io_service同样把IO操作转交给操作系统执行,但它不同步等待,而是立即返回。调用io_service的run()成员函数可以等待异步操作完成,当异步操作完成时io_service从操作系统获取结果,在调用handler执行后续逻辑。

1. handler  回调函数形式: void handler(const error_code &ec); void handler(const error_code &ec, std::size_type bytes_transferred); 2. io_service

 io_service类代表了系统里的异步处理机制(如epoll),必须在asio库里的其他对象之前初始化,其他对象则向io_service提交异步操作handler。

3. const_buffer

  数据缓冲区,保存了一个void*的内存地址和数据长度。

4. 网络通信相关

  asio支持TCP、UDP和ICMP通信协议,很好的封装了伯克利socket api。其中TCP部分定义了一些用于TCP通信的typedef类型,包括端点类endpoint、套接字类socket、流类iostream,以及接收器acceptor、解析器resolver等。 

class tcp { public: /// The type of a TCP endpoint. typedef basic_endpoint endpoint; /// The TCP socket type. typedef basic_stream_socket socket; /// The TCP acceptor type. typedef basic_socket_acceptor acceptor; /// The TCP resolver type. typedef basic_resolver resolver; /// The TCP iostream type. typedef basic_socket_iostream iostream; /// ...... };

endpoint包含IP地址和通信用的端口号。

  socket可以在构造时指定使用的协议或者endpoint,或者稍后调用成员函数connect()。连接成功后可以用local_endpoint()和remote_endpoint()获得连接两端的端点信息,用available()获取可读取的字节数,用receive()/read_some()和send()/write_some()读写数据,当操作完成后使用close()函数关闭socket。如果socket没有被关闭,则其析构时也会自动关闭。

  acceptor对应Socket API的accept()函数,用于服务器端。acceptor可以像传统socket API一样使用,open()打开端口,bind()绑定再用listen()侦听端口,但更方便的是使用它的构造函数,传入endpoint直接完成这三个动作。

5、IO模型

  在asio框架中,同步和异步区别

  (2)同步的io主要流程如下:

  

 

应用程序调用IO对象成员函数执行IO操作 IO对象向io_service 提出请求. io_service 调用操作系统的功能执行连接操作. 操作系统向io_service 返回执行结果. io_service将错误的操作结果翻译为boost::system::error_code类型,再传递给IO对象. 如果操作失败,IO对象抛出boost::system::system_error类型的异常.

 (1)而异步IO的处理流程则有些不同:

 

  

 

应用程序调用IO对象成员函数执行IO操作 IO对象请求io_service的服务 io_service 通知操作系统其需要开始一个异步连接. 操作系统指示连接操作完成, io_service从队列中获取操作结果 应用程序必须调用io_service::run()以便于接收结果 调用io_service::run()后,io_service返回一个操作结果,并将其翻译为error_code,传递到事件回调函数中 6、io_service对象

  io_service的作用: io_servie 实现了一个任务队列,这里的任务就是void(void)的函数。Io_servie最常用的两个接口是post和run,post向任务队列中投递任务,run是执行队列中的任务,直到全部执行完毕,并且run可以被N个线程调用。Io_service是完全线程安全的队列。

io_service对象提供的接口有run、run_one、poll、poll_one、stop、reset、dispatch、post,最常用的是run、post、stop:

post用于发布io事件,如timer,socket读写等,一般由asio框架相应对象调用,无需我们显式调用。 run用于监听io事件响应,并执行响应回调,对于异步io操作需要在代码中显式调用,对于同步io操作则由io对象隐式调用(并不是run函数,不过也是等待io事件)。

可见,io_service提供的是一个生产者消费者模型。在异步io操作中需要我们手动控制消费者,调用run函数,它的基本工作模式如下:

等待io事件响应,如果所有io事件响应完成则退出 等待到io事件响应后,执行其对应的回调 继续等待下一个io事件,重复1-2 从中可以看出,io_service是一个工作队列的模型。在使用过程中一般有如下几个需要注意的地方: (1) run函数在io事件完成后会退出,导致后续基于该对象的异步io任务无法执行

  由于io_service并不会主动常见调度线程,需要我们手动分配,常见的方式是给其分配一个线程,然后执行run函数。但run函数在io事件完成后会退出,线程会终止,后续基于该对象的异步io任务无法得到调度。

解决这个问题的方法是通过一个asio::io_service::work对象来守护io_service。这样,即使所有io任务都执行完成,也不会退出,继续等待新的io任务。

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有