boost------asio库的使用1(Boost程序库彻底开发指南)读书笔记

asio库基于操做系统提供的异步机制,采用前摄器设计模式(Proactor)实现了可移植的异步(或者同步)IO操做,并且并不要求多线程和锁定,有效地避免了多线程编程带来的诸多有害反作用。ios

 

目前asio主要关注于网络通讯方面,使用大量的类和函数封装了socket API,支持TCP、TCMP、UDP等网络通讯协议。但asio的异步操做并不局限于网络编程,它还支持串口读写、定时器、SSL等功能,并且asio是一个很好的富有弹性的框架,能够扩展到其余有异步操做须要的领域编程

 

 

概述设计模式

asio库基于前摄器模式封装了操做系统的select、poll/epoll、kqueue、overlapped I/O等机制,实现了异步IO模型。它的核心类io_service,至关于前摄器模式中的Proactor角色,asio的任何操做都须要有io_service的参与。网络

 

在同步模式下,程序发起一个IO操做,向io_service提交请求,io_service把操做转交给操做系统,同步地等待。当IO操做完成时,操做系统通知io_service,而后io_service再把结果发回给程序,完成整个同步流程。这个处理流程与多线程的join()等待方式很类似。多线程

 

在异步模式下,程序除了要发起的IO操做,还要定义一个用于回调的完成处理函数。io_service一样把IO操做转交给操做系统执行,但它不一样步等待,而是当即返回。调用io_service的run()成员函数能够等待异步操做完成,当异步操做完成时io_service从操做系统获取执行结果,调用完成处理函数。app

 

asio不直接使用操做系统提供的线程,而是定义了一个本身的线程概念:strand,它保证在多线程的环境中代码能够正确地执行,而无需使用互斥量。io_service::strand::wrap()函数能够包装一个函数在strand中执行。框架

 

asio库使用system库的error_code和system_error来表示程序运行的错误。异步

 

定时器

 

定时器是asio库里最简单的一个IO模型示范,提供等待时间终止的功能,经过它咱们能够快速熟悉asio的基本使用方法:socket

同步定时器

 

[cpp] view plain copyasync

 print?在CODE上查看代码片派生到个人代码片

  1. #include "stdafx.h"  
  2. #include "boost/asio.hpp"  
  3. #include "boost/date_time/posix_time/posix_time.hpp"  
  4. #include "iostream"  
  5. using namespace std;  
  6.   
  7.   
  8. int _tmain(int argc, _TCHAR* argv[])  
  9. {  
  10.     boost::asio::io_service ios;    // 因此的asio程序必需要有一个io_service对象  
  11.   
  12.     // 定时器io_service做为构造函数参数,两秒钟以后定时器终止  
  13.     boost::asio::deadline_timer t(ios, boost::posix_time::seconds(2));  
  14.   
  15.     cout << t.expires_at() << endl; // 查看终止的绝对事件  
  16.   
  17.     t.wait();                       // 调用wait同步等待  
  18.     cout << "hello asio" << endl;  
  19.   
  20.     return 0;  
  21. }  

 

 

能够把它与thread库的sleep()函数对比研究一下,二者都是等待,但内部机制完成不一样:thread库的sleep()使用了互斥量和条件变量,在线程中等待,而asio则是调用了操做系统的异步机制,如select、epoll等完成的。

 

 

异步定时器

下面的是异步定时器,代码大体与同步定时器相等,增长了回调函数,并使用io_service.run()和定时器的async_wait()方法

[cpp] view plain copy

 print?在CODE上查看代码片派生到个人代码片

  1. #include "stdafx.h"  
  2. #include "boost/asio.hpp"  
  3. #include "boost/date_time/posix_time/posix_time.hpp"  
  4. #include "iostream"  
  5. using namespace std;  
  6.   
  7.   
  8. void Print(const boost::system::error_code& error)  
  9. {  
  10.     cout << "hello asio" << endl;  
  11. }  
  12.   
  13.   
  14. int _tmain(int argc, _TCHAR* argv[])  
  15. {  
  16.     boost::asio::io_service ios;    // 因此的asio程序必需要有一个io_service对象  
  17.   
  18.     // 定时器io_service做为构造函数参数,两秒钟以后定时器终止  
  19.     boost::asio::deadline_timer t(ios, boost::posix_time::seconds(2));  
  20.   
  21.     t.async_wait(Print);                        // 调用wait异步等待  
  22.   
  23.     cout << "it show before t expired." << endl;  
  24.   
  25.     ios.run();  
  26.   
  27.     return 0;  
  28. }  

代码的前两行与同步定时器相同,这是全部asio程序基本的部分。重要的是异步等待async_wait(),它通知io_service异步地执行io操做,而且注册了回调函数,用于在io操做完成时由事件多路分离器分派返回值(error_code)调用

 

最后必须调用io_service的run()成员函数,它启动前摄器的事件处理循环,阻塞等待全部的操做完成并分派事件。若是不调用run()那么虽然操做被异步执行了,但没有一个等待它完成的机制,回调函数将得不到执行机会。

 

 

异步定时器使用bind

异步定时器中因为引入了回调函数,所以产生了不少的变化,能够增长回调函数的参数,使它可以作更多的事情。但async_wait()接受的回调函数类型是固定的,必须使用bind库来绑定参数以适配它的接口

   下面实现一个能够定时执行任意函数的定时器AsynTimer(asyctimer),它持有一个asio定时器对象和一个计数器,还有一个function对象来保存回调函数

[cpp] view plain copy

 print?在CODE上查看代码片派生到个人代码片

  1. #include "stdafx.h"  
  2. #include "boost/asio.hpp"  
  3. #include "boost/date_time/posix_time/posix_time.hpp"  
  4. #include "boost/bind.hpp"  
  5. #include "boost/function.hpp"  
  6. #include "iostream"  
  7. using namespace std;  
  8.   
  9.   
  10. class AsynTimer  
  11. {  
  12. public:  
  13.     template<typename F>                              // 模板类型,能够接受任意可调用物  
  14.     AsynTimer(boost::asio::io_service& ios, int x, F func)  
  15.         :f(func), count_max(x), count(0),               // 初始化回调函数和计数器  
  16.         t(ios, boost::posix_time::millisec(500))        // 启动计时器  
  17.     {  
  18.         t.async_wait(boost::bind(&AsynTimer::CallBack,  // 异步等待计时器  
  19.             this, boost::asio::placeholders::error));   // 注册回调函数  
  20.     }  
  21.   
  22.     void CallBack(const boost::system::error_code& error)  
  23.     {  
  24.         if (count >= count_max)   // 若是计数器达到上限则返回  
  25.         {  
  26.             return;  
  27.         }  
  28.         ++count;  
  29.         f();                     // 调用function对象  
  30.   
  31.         // 设置定时器的终止时间为0.5秒以后  
  32.         t.expires_at(t.expires_at() + boost::posix_time::microsec(500));  
  33.         // 再次启动定时器,异步等待  
  34.         t.async_wait(boost::bind(&AsynTimer::CallBack, this, boost::asio::placeholders::error));  
  35.     }  
  36.   
  37. private:  
  38.     int count;  
  39.     int count_max;  
  40.     boost::function<void()> f;        // function对象,持有无参无返回值的可调用物  
  41.     boost::asio::deadline_timer t;  // asio定时器对象  
  42. };  
  43.   
  44. // 第一个回调函数  
  45. void print1()  
  46. {  
  47.     cout << "hello asio" << endl;  
  48. }  
  49.   
  50. // 第二个回调函数  
  51. void print2()  
  52. {  
  53.     cout << "hello boost" << endl;  
  54. }  
  55.   
  56.   
  57. int _tmain(int argc, _TCHAR* argv[])  
  58. {  
  59.     boost::asio::io_service ios;  
  60.   
  61.     AsynTimer t1(ios, 10, print1); // 启动第一个定时器  
  62.     AsynTimer t2(ios, 10, print2); // 启动第二个定时器  
  63.   
  64.     ios.run();  // io_service等待异步调用结束  
  65.   
  66.     return 0;  
  67. }  

 

注意在async_wait()中bind的用法,CallBack是AsynTimer的一个成员函数,所以须要绑定this指针,同时还使用了asio下子名字空间placeholders下的一个占位符error,他的做业相似于bind库的占位符_一、_2,用于传递error_code值。

 

接下来是AsynTimer的主要功能函数CallBack,它符合async_wait()对回调函数的要求,有一个error_code参数,当定时器终止时它将被调用执行

 

CallBack函数内部累加器,若是计数器未达到上限则调用function对象f,而后从新设置定时器的终止时间,再次异步等待被调用,从而达到反复执行的目的

相关文章
相关标签/搜索