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?

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

能够把它与thread库的sleep()函数对比研究一下,二者都是等待,但内部机制完成不一样:thread库的sleep()使用了互斥量和条件变量,在线程中等待,而asio则是调用了操做系统的异步机制,如select、epoll等完成的。
异步定时器
下面的是异步定时器,代码大体与同步定时器相等,增长了回调函数,并使用io_service.run()和定时器的async_wait()方法
[cpp] view plain copy
print?

- #include "stdafx.h"
- #include "boost/asio.hpp"
- #include "boost/date_time/posix_time/posix_time.hpp"
- #include "iostream"
- using namespace std;
-
-
- void Print(const boost::system::error_code& error)
- {
- cout << "hello asio" << endl;
- }
-
-
- int _tmain(int argc, _TCHAR* argv[])
- {
- boost::asio::io_service ios; // 因此的asio程序必需要有一个io_service对象
-
- // 定时器io_service做为构造函数参数,两秒钟以后定时器终止
- boost::asio::deadline_timer t(ios, boost::posix_time::seconds(2));
-
- t.async_wait(Print); // 调用wait异步等待
-
- cout << "it show before t expired." << endl;
-
- ios.run();
-
- return 0;
- }
代码的前两行与同步定时器相同,这是全部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?

- #include "stdafx.h"
- #include "boost/asio.hpp"
- #include "boost/date_time/posix_time/posix_time.hpp"
- #include "boost/bind.hpp"
- #include "boost/function.hpp"
- #include "iostream"
- using namespace std;
-
-
- class AsynTimer
- {
- public:
- template<typename F> // 模板类型,能够接受任意可调用物
- AsynTimer(boost::asio::io_service& ios, int x, F func)
- :f(func), count_max(x), count(0), // 初始化回调函数和计数器
- t(ios, boost::posix_time::millisec(500)) // 启动计时器
- {
- t.async_wait(boost::bind(&AsynTimer::CallBack, // 异步等待计时器
- this, boost::asio::placeholders::error)); // 注册回调函数
- }
-
- void CallBack(const boost::system::error_code& error)
- {
- if (count >= count_max) // 若是计数器达到上限则返回
- {
- return;
- }
- ++count;
- f(); // 调用function对象
-
- // 设置定时器的终止时间为0.5秒以后
- t.expires_at(t.expires_at() + boost::posix_time::microsec(500));
- // 再次启动定时器,异步等待
- t.async_wait(boost::bind(&AsynTimer::CallBack, this, boost::asio::placeholders::error));
- }
-
- private:
- int count;
- int count_max;
- boost::function<void()> f; // function对象,持有无参无返回值的可调用物
- boost::asio::deadline_timer t; // asio定时器对象
- };
-
- // 第一个回调函数
- void print1()
- {
- cout << "hello asio" << endl;
- }
-
- // 第二个回调函数
- void print2()
- {
- cout << "hello boost" << endl;
- }
-
-
- int _tmain(int argc, _TCHAR* argv[])
- {
- boost::asio::io_service ios;
-
- AsynTimer t1(ios, 10, print1); // 启动第一个定时器
- AsynTimer t2(ios, 10, print2); // 启动第二个定时器
-
- ios.run(); // io_service等待异步调用结束
-
- return 0;
- }
注意在async_wait()中bind的用法,CallBack是AsynTimer的一个成员函数,所以须要绑定this指针,同时还使用了asio下子名字空间placeholders下的一个占位符error,他的做业相似于bind库的占位符_一、_2,用于传递error_code值。
接下来是AsynTimer的主要功能函数CallBack,它符合async_wait()对回调函数的要求,有一个error_code参数,当定时器终止时它将被调用执行
CallBack函数内部累加器,若是计数器未达到上限则调用function对象f,而后从新设置定时器的终止时间,再次异步等待被调用,从而达到反复执行的目的