官网参考示例:
https://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/example/
这个是/async_tcp_client示例:
https://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/example/timeouts/async_tcp_client.cpp
原文:http://www.voidcn.com/article/p-efmozrnt-bex.html
异步定时器 和 同步定时器,简单示例:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <time.h>
#include <boost/functional.hpp>//可调用实体对象
using std::cout;
using std::endl;
using boost::asio::io_service;
using boost::asio::deadline_timer;
using std::bind;
using std::function;
using boost::posix_time::millisec;
using boost::posix_time::microsec;
//同步定时器
void test1()
{
io_service ios;//所有的asio程序必须要有一个io_service对象
deadline_timer t(ios,boost::posix_time::seconds(5));//5秒钟后定时器终止
float start_t = clock();
cout<<t.expires_at()<<endl;//查看终止的决定时间
cout<< "time_start = "<< clock()<<endl;
t.wait();//调用wait()同步等待 ----------------------此处阻塞
cout<< "time_end= "<< clock()<<endl;
cout<< "time_use = "<< (clock()-start_t)/CLOCKS_PER_SEC<<endl;
cout<<"hello asio"<<endl;
/*
可以把它与thread库的sleep()函数对比研究一下,两种虽然都是等待,但内部机制完全不同:
thread库的sleep()使用了互斥量和条件变量,在线程中等待,而asio则是调用了操作系统的异步机制,
如select,epool等完成。
同步定时器的用法很简单,但它演示了asio程序的基本结构和流程:
一个asio程序首先要定义一个io_service对象,它是前摄器模式中最重的proactor角色,
然后我们声明一个IO操作(这里是定时器),并把它挂接在io_service上,
再然后就可以执行后续的 同步或异步操作。
*/
}
/*
异步定时器:代码大致与同步定时器相同,增加了回调函数,
并使用io_service_run()和定时器的async_wait()
首先我们要定义回调函数,asio库要求回调函数只能有一个参数,
而且这个参数必须是const asio::error_code&类型
*/
void myprint(boost::system::error_code ec)
{
for(int i=0;i<5;i++)
cout<<"hello asio"<<endl;
}
void test2()
{
io_service ios;
deadline_timer t(ios,boost::posix_time::seconds(3));
t.async_wait(myprint);//异步等待,传入回调函数,立即返回
cout<<"it show before t expired."<<endl;
ios.run();//很重要,异步IO必须 ----------------------此处阻塞,保证
cout<<"runned"<<endl;//将与hello asio一起输出,说明run()是阻塞函数
/*
异步等待async_wait(),它通知io_service异步的执行IO操作,
用于在IO操作完成时有事件多路分离器分派返回值(error_code)调用。
最后我们必须调用io_service的run()成员函数,它启动前摄器的事件处理循环,
阻塞等待所有的操作完成并分派事件。如果不调用run()那么虽然被异步执行了,
但没有一个等待他完成的机制,回调函数将得不到执行的机会。
*/
}
一个可以定时执行任意函数的定时器类 a_timer(asyc timer),它持有一个asio定时器对象和一个计数器,还有一个function对象用来保存回调函数;如下:
class a_timer
{
private:
int count,cout_max; //计数器成员变量
function<void()> f; //function对象,持有无参数无返回的可调用实体
deadline_timer t;//asio定时器
public:
/*
构造函数初始化成员变量,将计数器清理,设置计数器的上限,拷贝存储回调函数,
并立即启动定时器之所以要"立即"启动,是因为我们必须包装在io_service.run()之前,
至少有一个异步操作在执行,否则io_service.run()会因为没有事件处理而立即不等待返回。
*/
//模板类型,可接受任意可调用物
template<typename F> a_timer(io_service& ios,int x,F func):f(func),
cout_max(x),count(0),t(ios,microsec(500))
{
t.async_wait(bind(&a_timer::call_func,this,std::placeholders::_1));
/*
占位符_1,_2,用于传递errror_code值。
bind(&a_timer::call_func,this,std::placeholders::_1)将 传递进去的函数,绑定到this指针,
返回一个可调用实体
*/
}
//call_func()内部累加计数器,如果计数器未达到上限则调用function对象f,
//然后重新设置定时器的终止时间,再次异步等待被调用,从而达到反复执行的目的。
void call_func(const boost::system::error_code &)
{
if(count >= cout_max)
{
return;
}
++count;
f();//外部要执行的函数
t.expires_at(t.expires_at()+millisec(500));
//设置定时器的终止时间为0.5秒之后
// 重新设定计时器终止时间,使得可以可以一直执行下去,直到终止条件触发;
t.async_wait(bind(&a_timer::call_func,this,std::placeholders::_1));
}
};
void print1(int index)
{
cout<<"hello asio:"<<index<<endl;
}
void print2()
{
cout<<"hello boost *********** "<<endl;
cout<<"hello boost *********** "<<endl;
cout<<"hello boost *********** "<<endl;
cout<<"hello boost *********** "<<endl;
cout<<"hello boost *********** "<<endl;
cout<<"hello boost *********** "<<endl;
}
void test3()
{
io_service ios;
a_timer a(ios,5,std::bind(print1,2));//启用第一个定时器
a_timer at(ios,3,print2);//启用第二个定时器
ios.run();//ios等待异步调用结束
}