boost asio定时器学习

时间:2022-09-08 23:14:21

        Asio是基于操作系统提供的异步机制,其主要用于网络编程方面,使用了大量的类和函数封装了socket API。

       使用asio不需要编译,但是它依赖于其它一些boost组件,包括boost_system和boost datetime库,用于提供系统错误和时间支持。

     同步vs异步

         asio的任何操作都需要io_service参与,它是asio的核心类。
         同步和异步编程有很大的不同。在同步编程中,所有的操作是按照顺序执行的,比如socket接受客户端的请求,然后响应,返回写入到socket中,其中每个操作都是阻塞的。因为每个操作阻塞,不可能让服务器只服务这一个请求。所以一般服务器采用多线程,一个socket在那接受客户端请求,另外创建一些线程用于给客户端服务。因此,同步的服务器/客户端一般是多线程的。在asio中,在同步模式下,程序发起一个IO操作,向io_service提交请求,io_service把操作交给操作系统,同步等待。当IO操作完成,操作系统通知io_service,然后io_service把结果发回给程序,完成整个流程。
         
        异步编程则是事件驱动,虽然启动了一个操作,但是你不知道它何时结束,只是提供一个回调给你,当操作结束,调用这个API,返回操作结束。在异步模式下,程序除了要发起IO操作,还定义一个用于回调的完成处理函数。io_service同样把IO操作交给操作系统执行,但是它不同步等待,而是立刻返回。调用io_service的run()可以等待异步操作完成。当异步操作完成,io_service从操作系统获取执行结果,调用完成处理函数。
 
         asio使用system库的error_code和system_error来表示程序运行时错误。

     同步定时器

         先看个同步定时器。
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

using namespace std;
using namespace boost::asio;
using namespace boost;


int main()
{
    io_service ios;           //所有asio程序必须有一个io_service对象

	deadline_timer t(ios,posix_time::seconds(2));    //定时器,两秒后定时器终止
	cout<<t.expires_at()<<endl;                      //查看到期的时间
	
	t.wait();                                       //wait()同步等待
	cout << "hello asio" << endl;
 
	

}
         编译的时候只要连接lboost_system即可。

     异步定时器

        异步定时器和同步类似,只是加了回调函数,使用了io_service。run()方法。
       
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

using namespace std;
using namespace boost::asio;
using namespace boost;

void print(const system::error_code &e)         //注意此处要加const,否则报错
{
    cout<<"hello asio"<<endl;
}

int main()
{
    io_service ios;

	deadline_timer t(ios,posix_time::seconds(2));
//	cout<<t.expires_at()<<endl;
	
//	t.wait();
//	cout << "hello asio" << endl;
    t.async_wait(print);
	cout<<"before"<<endl;
	ios.run();
	cout<<"end"<<endl;

}

       首先来看回调函数,asio库要求回调函数只有一个参数,而且这个参数必须是const asio::error_code &类型。这就很不方便,于是可以使用bind来绑定参数。
        
#include <iostream>
#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

#include <boost/date_time/posix_time/posix_time.hpp>

using namespace std;
using namespace boost::asio;
using namespace boost;

class a_timer{
	private:
		int count,count_max;
		function<void()> f;
		deadline_timer t;         //asio定时器对象
	public:
		template<typename F>
			a_timer(io_service &ios, int x, F func) : f(func), count_max(x), count(0), t(ios, posix_time::millisec(500))
		{                                              //初始化回调函数和计数器,启动定时器
            t.async_wait(bind(&a_timer::call_func, this, placeholders::error));         //异步等待计时器 注册回调函数
		}
		void call_func(const system::error_code & e)
	    {
            if(count >= count_max)
				return;
			++count;
			f();
			t.expires_at(t.expires_at() + posix_time::millisec(500));
            t.async_wait(bind(&a_timer::call_func, this, placeholders::error));
		}

};

void print1()
{
    cout << "hello asio" <<endl;
}

void print2()
{
    cout << "hello boost" <<endl;
}

int main()
{
    io_service ios;
    a_timer at1(ios, 5, print1 );
    a_timer at2(ios, 5, print2 );
	ios.run();                //io_server 等待异步调用结束

}