【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!
"; /* “Hello,world” 。 */ return 0; }

説明:deadline_timer::wait()関数呼び出しは、タイマが終了するまで(タイマが作成されてから5秒後に終了するまで)返されます.1つのdeadline timerは、通常、「expired(終了)」または「not expired(終了しない)」の2つのステータスの1つです.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!
"; } 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 << "
"; ++(*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 << "
"; return 0; }
、Asioを使用して繰り返しタイマを実現するには、コールバック関数でタイマの終了時間を変更し、新しい非同期待機を開始する必要があります.
これは、コールバック関数がタイマオブジェクトを変更する権限を持つ必要があることを意味します.このためprint関数に2つの新しいパラメータを追加します.タイマーオブジェクトへのポインタです
タイマが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_サービス::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_ << "
"; } void print1() { if (count_ < 10) { std::cout << "Timer 1: " << count_ << "
"; ++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_ << "
"; ++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_Services::run()は、プライマリスレッドと追加スレッドの2つのスレッドで呼び出されます.これらはboost::threadオブジェクトに依存して完了します.単一スレッドで呼び出されるようにboost::asio::io_サービス::run()の同時呼び出しは、「作業」がないまで継続します.バックグラウンドスレッドは、すべての非同期操作が完了するまで終了しません.2.1つのマルチスレッドプログラムにおいて、同じ共有リソースにアクセスする場合、非同期操作は同期されなければならない.この例では、print 1およびprint 2関数で使用される共有リソースはstd::coutおよびcount_データ・メンバー.3、一対のboost::asio::deadline_を初期化する以外はtimerメンバー変数に加えて、コンストラクション関数はboost::asio::strandタイプstrand_を初期化します.メンバー変数.boost::asio::strandオブジェクト保証:それによって実行が割り当てられた一般的な操作では、1つの操作が完了してから次の操作に進むことができます.