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 等待异步调用结束 }