boostライブラリが動作(39)ネットワークUDP非同期サービス端の9

2761 ワード

先に作成したUDPサーバとクライアントは,いずれも同期方式であり,つまりデータを受信すると,他のことに関与して実行できない.インタフェーススレッドのみのプログラムで、マルチスレッドを作成したくない場合、複雑さが増す場合、非同期のUDPサーバやクライアントを作成する方法もあります.これにより、単一スレッドの単純性もあれば、インタフェースの迅速な応答の特性を任意に操作することができます.boostライブラリでio_を使用サービスオブジェクトが非同期を実現するのは容易であり,パッケージのインタフェースが簡単で明瞭であるためである.具体的なコードは以下の通りです.
// boost_028.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <ctime>

#include <boost/asio/ip/tcp.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/array.hpp>

#include <iostream>
#include <string>

//  UDP    
using boost::asio::ip::udp;

//           。
std::string make_daytime_string()
{
	using namespace std; //    time_t, time   ctime;
	time_t now = time(0);
	return ctime(&now);
}

//
//      UDP      。
//      :      2013-08-25 
//QQ: 9073204
//
class UdpTimeServer
{
public:
	//  IO  ,      UDP SOCKET,IPV4  ,   13
	UdpTimeServer(boost::asio::io_service& ioService)
		:m_sockUdp(ioService,  udp::endpoint(udp::v4(), 13))
	{
		//       。
		RecvTime();
	}
private:
	//         。
	void RecvTime(void)
	{
		//      
		m_sockUdp.async_receive_from(
			boost::asio::buffer(m_recvBuf), m_endpointRemote,
			boost::bind(&UdpTimeServer::handleRecvTime, this,
			boost::asio::placeholders::error,
			boost::asio::placeholders::bytes_transferred));
	}

	//         ,          
	void handleRecvTime(const boost::system::error_code& error,
		std::size_t /*bytes_transferred*/)
	{
		//      ,             。
		if (!error || error == boost::asio::error::message_size)
		{
			boost::shared_ptr<std::string> strMessage(
				new std::string(make_daytime_string()));

			m_sockUdp.async_send_to(boost::asio::buffer(*strMessage), m_endpointRemote,
				boost::bind(&UdpTimeServer::handleSendTime, this, strMessage,
				boost::asio::placeholders::error,
				boost::asio::placeholders::bytes_transferred));

			//        。
			RecvTime();
		}
	}

	//                  。
	void handleSendTime(boost::shared_ptr<std::string> /*strMessage*/,
			const boost::system::error_code& /*error*/,
			std::size_t /*bytes_transferred*/)
	{

	}

private:
	udp::socket m_sockUdp; //    SOCKET。
	udp::endpoint m_endpointRemote; //          。
	boost::array<char, 1> m_recvBuf; //       。
};

void TestUdp(void)
{
	boost::asio::io_service ioService;
	UdpTimeServer udpTimeServer(ioService);
	ioService.run();
}


int _tmain(int argc, _TCHAR* argv[])
{
	//
	TestUdp();

	return 0;
}

この例では、io_を採用したサーバUdpTimeServerを主にカプセル化しています.サービスオブジェクトとsocketオブジェクトの非同期特性を構築し、イベント応答があってから対応する操作を実行しますが、これは前の同期方式よりも複雑ですが、マルチスレッド間の同期問題を回避します.