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

目前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从操作系统获取执行结果,调用完成处理函数。

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

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

定时器

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

同步定时器

#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()方法

#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对象来保存回调函数

#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库的占位符_1、_2,用于传递error_code值。

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

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

boost------asio库的使用1(Boost程序库完全开发指南)读书笔记的更多相关文章

  1. boost------asio库的使用2(Boost程序库完全开发指南)读书笔记

    网络通信 asio库支持TCP.UDP.ICMP通信协议,它在名字空间boost::asio::ip里提供了大量的网络通信方面的函数和类,很好地封装了原始的Berkeley Socket Api,展现 ...

  2. [转] boost------ref的使用(Boost程序库完全开发指南)读书笔记

    http://blog.csdn.net/zengraoli/article/details/9663057 STL和Boost中的算法和函数大量使用了函数对象作为判断式或谓词参数,而这些参数都是传值 ...

  3. boost------signals2的使用1(Boost程序库完全开发指南)读书笔记

    signals2基于Boost的另一个库signals,实现了线程安全的观察者模式.在signals2库中,观察者模式被称为信号/插槽(signals and slots),他是一种函数回调机制,一个 ...

  4. boost------ref的使用(Boost程序库完全开发指南)读书笔记

    STL和Boost中的算法和函数大量使用了函数对象作为判断式或谓词参数,而这些参数都是传值语义,算法或函数在内部保修函数对象的拷贝并使用,例如: #include "stdafx.h&quo ...

  5. boost------function的使用(Boost程序库完全开发指南)读书笔记

    function是一个函数对象的“容器”,概念上像是c/c++中函数指针类型的泛化,是一种“智能函数指针”.它以对象的形式封装了原始的函数指针或函数对象,能够容纳任意符合函数签名的可调用对象. 因此, ...

  6. boost------bind的使用(Boost程序库完全开发指南)读书笔记

    bind是c++98标准库中函数适配器bind1st/bind2nd的泛化和增强,可以适配任意的可调用类型,包括函数指针.函数引用.成员函数指针和函数对象. 1.工作原理 bind并不是一个单独的类或 ...

  7. boost------signals2的使用2(Boost程序库完全开发指南)读书笔记

    1.应用于观察者模式 本小节将使用signals2开发一个完整的观察者模式示例程序,用来演示信号/插槽的用法.这个程序将模拟一个日常生活场景:客人按门铃,门铃响,护士开门,婴儿哭闹. Ring.h: ...

  8. Boost程序库完全开发指南——深入C++“准”标准库(第3版)

    内容简介  · · · · · · Boost 是一个功能强大.构造精巧.跨平台.开源并且完全免费的C++程序库,有着“C++‘准’标准库”的美誉. Boost 由C++标准委员会部分成员所设立的Bo ...

  9. Boost.Asio 网络编程([译]Boost.Asio基本原理)

    转自:https://m.w3cschool.cn/nlzbw/nlzbw-3vs825ya.html Boost.Asio基本原理 这一章涵盖了使用Boost.Asio时必须知道的一些事情.我们也将 ...

随机推荐

  1. Eclipse中文乱码解决汇总(应该比较全):

    Eclipse中文乱码解决汇总(应该比较全,欢迎补充): 方法一: 把GBK改成utf-8. 方法二: Window->preference->general->content ty ...

  2. opencart 百度登录和百度钱包支付插件 响应式适应pc/mobile

    OpenCart(http://www.opencart.com/,http://www.opencartchina.com/)是国外著名的开源电子商务系统, 优势在于前台界面的设计非常适合欧美购物者 ...

  3. PHP substr截取中文字符出现乱码的问题解疑

    我们在使用PHP substr截取中文字符的时候,经常会出现乱码的情况,导致程序无法正常运行,这时怎么引起的呢?通过分析,我们知道,主要是substr可能硬生生的将一个中文字符“锯”成两半.解决办法: ...

  4. HierarchyView的实现原理和Android设备无法使用HierarchyView的解决方法

    声明:由于本人一直用eng版的真机调试,所以此方法没有用过,记录在这里,有机会验证 ---------------------------------------------------------- ...

  5. Python疑问系列

    最近在看python源码 ------点点滴滴做个记录. 预计要分的系列: 1. import 分析 2. 主要bytecode 分析 3. python启动分析 4. object对象分析 最后希望 ...

  6. 获取网络图片的大小 改变 图片色值 灰度什么的方法集合-b

    直接上代码了 头文件 // 图片处理 0 半灰色  1 灰度   2 深棕色    3 反色 +(UIImage*)imageWithImage:(UIImage*)image grayLevelTy ...

  7. Elasticsearch客户端大全 http://www.searchtech.pro/elasticsearch-clients

    Elasticsearch有各种语言的客户端,下面一一列出来: Perl ElasticSearch.pm: Perl客户端 Python pyes: Python客户端pyelasticsearch ...

  8. “未能加载文件或程序集file:///E:/MoneySet.dll或它的某一个依赖项,试图加载格式不正确的程序,行203,位置5. 文件:MReportSet.resx”,

    http://bbs.csdn.net/topics/390334265 1.右键卸载项目2.右键选择编辑工程文件,在打开的文件的最后一行</project>之前加以下内容: <Pr ...

  9. Java 去除HTML标签转化成纯文本

    package com.ahgw.common.global; import java.util.regex.Pattern; /** * 截取HTML代码 * * @author YangJunpi ...

  10. Java 引用 WeakReference

    Reference 是一个抽象类,而 SoftReference,WeakReference,PhantomReference 以及 FinalReference 都是继承它的具体类.接下来我们来分别 ...