【Boost.Asio学习笔记】C/S通信简例

一、同步:定时器中执行一个阻塞等待

#include <iostream>
#include <boost/asio.hpp>
#include<boost/date_time/posix_time/posix_time.hpp>
int main()
{
	boost::asio::io_service io; 
	boost::asio::deadline_timer t(io,boost::posix_time::seconds(5));
	t.wait();
	std::cout << "Hello, world!\n"; /* 最后我们打印出“Hello,world”信息以显示定时器已经终止。 */
	return 0;
}

说明:deadline_timer::wait()函数调用直到定时器终止(从定时器被创建算起,五秒后终止)才会返回。
一个deadline timer 通常是下面两种状态中的一种:"expired(终止)" 或"not expired(不终止)"。
deadline_timer::wait()函数如果被一个已经终止的定时器调用, 它将立即返回。

二、异步:

#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
void print(const boost::system::error_code & e) /* 异步等待结束将被调用的函数 */
{
	std::cout << "Hello, world!\n";
}
int main()
{
	boost::asio::io_service io;
	boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
	t.async_wait(print); /* 执行一个异步等待,并传入上面定义的print回调句柄。 */
	io.run();
	return 0;
}

使用Asio的异步功能意味着当一个异步操作完成时一个回调函数将被调用。在本程序中我们定义一个名为“print”的函数,在异步等待结束后这个函数将被调用。

三、异步结束后,在回调函数中重启异步操作

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
void print(const boost::system::error_code & e,boost::asio::deadline_timer* t, int* count)
{
	if (*count < 5) {
		std::cout << *count << "\n";
		++(*count);
		/* 推迟定时器的终止时间。在原先的终止时间上增加延时,确保定时器不会在处理回调函数所需时间内到期 */
		t->expires_at(t->expires_at() + boost::posix_time::seconds(1));
		t->async_wait(boost::bind(print, boost::asio::placeholders::error, t, count));
	}
}
int main()
{
	boost::asio::io_service io;
	int count = 0;
	boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
	/* 在第四步中,当在主函数中的调用boost::asio::deadline_timer::async_wait() 函数时,
	我们绑定print函数所需要的附加参数 */
	t.async_wait(boost::bind(print, boost::asio::placeholders::error, &t, &count));
	io.run();
	std::cout << "Final count is " << count << "\n";
	return 0;
}
1, 使用Asio实现一个重复定时器,你必须在你的回调函数中去改变定时器的终止时间,然后开始一个新的异步等待。
显然这意味着回调函数必须拥有改变定时器对象的权限。为此我们为print函数增加两个新参数。一个指向定时器对象的指针,
一个用于当定时器第6次被激活时我们可以中止程序的计数器 
2,在定时器中启动一个新的异步等待。我们必须使用boost::bind() 函数给你的回调函数绑定额外的参数,
因为boost::asio::deadline_timer::async_wait() 函数只期望得到一个拥有void(constboost::system::error_code&)签名的函数指针(或函数对象)。

四、使用类成员函数作为回调句柄。程序完成和上面完全同样的功能

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
class printer
{
public:
	printer(boost::asio::io_service& io) : timer_(io, boost::posix_time::seconds(1)), count_(0) {
		timer_.async_wait(boost::bind(&printer::print, this));
	}
	~printer() {
		std::cout << "Final count is " << count_ << " ";
	}
	void print() {
		if (count_ < 5) {
			std::cout << count_ << " ";
			++count_;
			timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
			timer_.async_wait(boost::bind(&printer::print, this));
		}
	}
private:
	boost::asio::deadline_timer timer_;
	int count_;
};
int main()
{
	boost::asio::io_service io;
	printer p(io);
	io.run();
	return 0;
}
五、使用boost::asio::strand 类来创建多线程程序中的同步回调句柄。

 单线程通常是使用Asio开发应用程序最好的方式。下面是Asio在程序中的局限性,尤其是服务器方面,包括:
操作需要较长时间处理才能完成时弱响应   
在大规模的多处理机系统中表现不佳 
如果你发现自己陷入这些局限时,一个可供选择的方法是创建一个每个线程都调用boost::asio::io_service::run()的线程池。不过,因为这允许并发操作,当访问一个共享、非线程安全的资源时,我们需要一个同步方式。

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
class printer
{
public:
	printer(boost::asio::io_service& io) : strand_(io), timer1_(io, boost::posix_time::seconds(1)), timer2_(io, boost::posix_time::seconds(1)),
      count_(0) {
		  timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));
		  timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));
	}
	~printer() {
		std::cout << "Final count is " << count_ << "\n";
	}
	void print1() {
		if (count_ < 10) {
			std::cout << "Timer 1: " << count_ << "\n";
			++count_;
			timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1));
			timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));
		}
	}
	void print2() {
		if (count_ < 10) {
			std::cout << "Timer 2: " << count_ << "\n";
			++count_;
			timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1));
			timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));
		}
	}
private:
	boost::asio::strand strand_;
	boost::asio::deadline_timer timer1_;
	boost::asio::deadline_timer timer2_;
	int count_;
};
int main()
{
	boost::asio::io_service io;
	printer p(io);
	boost::thread t(boost::bind(&boost::asio::io_service::run, &io));
	io.run();
	t.join();
	return 0;
}


1,在主函数中,boost::asio::io_service::run() 现在被两个线程调用:主线程和一个附加线程。这一切依赖于boost::thread对象来完成。正如它被一个单线程调用一样,boost::asio::io_service::run() 的并发调用会一直持续到无任何“工作”可做。后台线程直到所有异步操作都完成后才会退出。
2, 在一个多线程程序中,当访问同一共享资源时,异步操作必须是同步的。在本例中,print1和print2函数使用的共享资源为std::cout 和count_数据成员。
3, 除了初始化一对boost::asio::deadline_timer 成员变量外,构造函数还初始化一个boost::asio::strand类型的strand_成员变量。boost::asio::strand 对象保证:对于通过它来分派执行的众操作中,只有一个操作执行完成之后才允许进入下一个操作。


你可能感兴趣的:(thread,多线程,timer,IO,service,System)