ACE中的reactor模式学习




这两天在学习C++网络编程卷二,第二章开始讲到reactor模式,这两天结合书上的例子,写了个简单的echo server端程序,代码如下:
#include <ace/ACE.h>
#include <ace/OS_NS_string.h>
#include <ace/os_include/os_stdint.h>
#include <ace/OS_NS_stdlib.h>
#include <ace/OS_NS_errno.h>
#include <ace/OS_NS_unistd.h>
#include <ace/OS_NS_sys_time.h>
#include <ace/OS_main.h>

#include <ace/Basic_Types.h>
#include <ace/Handle_Set.h>
#include <ace/Map_Manager.h>
#include <ace/Null_Mutex.h>
#include <ace/Process.h>
#include <ace/Thread_Manager.h>
#include <ace/TSS_T.h>

#include <ace/INET_Addr.h>
#include <ace/SOCK_Acceptor.h>
#include <ace/SOCK_Connector.h>
#include <ace/SOCK_Stream.h>

#include <ace/FILE_Connector.h>
#include <ace/FILE_Addr.h>
#include <ace/FILE_IO.h>

#include <ace/Event_Handler.h>
#include <ace/Reactor.h>

//#include <stdarg.h>
#include <assert.h>

const u_short LISTEN_PORT = 8001;




#include "test_fwd.h"

class EchoEventHandler : public ACE_Event_Handler
{
public:
	EchoEventHandler(ACE_Reactor* reactor, ACE_Time_Value timeout_time)
		: ACE_Event_Handler(reactor), timeout_time_(timeout_time) , timer_id_(0), is_ok_(false)
	{
	}

	// 在析构时做remove_handler时 会自己去调用handle_close()
	virtual ~EchoEventHandler() 
	{
		if(is_opened())
		{
			reactor()->remove_handler(this,  ACE_Event_Handler::READ_MASK);
		}
	}

	void close()
	{
		reactor()->remove_handler(this,  ACE_Event_Handler::READ_MASK);
	}

	virtual int open()
	{
		// 测试退出的流程
		// return -1;

		// 注册自己为反应器的读处理事件
		if (0 != reactor()->register_handler(this, ACE_Event_Handler::READ_MASK))
		{
			ACE_ERROR_RETURN((LM_ERROR, "register read event fail\n"), -1);
		}
		is_ok_ = true;

		// 同步当前时间
		last_proc_time_ = ACE_OS::gettimeofday();

		// 注册定时器
		ACE_Time_Value reschedule(timeout_time_.sec() / 4);
		timer_id_ = reactor()->schedule_timer(
			this,   // timer event handler, should implement virtual function handle_timeout
			0,  // handle_timeout() callback args
			timeout_time_, // delay time
			reschedule); // schedule interval

		if (timer_id_ < 0)
		{
			ACE_ERROR_RETURN((LM_ERROR, "register timer schedule fail, errno=%d\n", ACE_ERRNO_GET), -1);
		}
		
		// 测试退出的流程
		return -1;
		
		return 0;
	}

	bool is_opened()
	{
		return is_ok_;
	}

	virtual int handle_input(ACE_HANDLE handle = ACE_INVALID_HANDLE)
	{
		ACE_DEBUG((LM_ERROR, "get data from stream[%d]\n", peer().get_handle()));

		// 更新proc time
		last_proc_time_ = ACE_OS::gettimeofday();

		// 通过stream收发数据
		char recvbuf[64];
		ACE_OS::memset(recvbuf, 0, sizeof(recvbuf));
		peer().enable(ACE_NONBLOCK);
		ssize_t recvlen = peer().recv(recvbuf, sizeof(recvbuf) - 1);

		if (recvlen < 0)
		{
			ACE_ERROR_RETURN((LM_ERROR, "recv buffer fail, errno=%d \n", errno), -1);
		}
		else if (0 == recvlen)
		{
			ACE_ERROR_RETURN((LM_ERROR, "client disconnect\n"), -1);
		}

		ACE_DEBUG((LM_ERROR, "recv buffer(%d):%s\n", recvlen,  recvbuf));
		ssize_t sendlen = peer().send_n(recvbuf, recvlen);

		if (sendlen != recvlen)
		{
			ACE_ERROR_RETURN((LM_ERROR, "send back buffer fail \n"), -1);
		}

		return 0;
	}

	// 当handle_*方法返回-1时,会自动调用handle_close方法
	virtual int handle_close(ACE_HANDLE handle = ACE_INVALID_HANDLE,
		ACE_Reactor_Mask mask = 0)
	{
		ACE_DEBUG((LM_ERROR, "event handle [fd=%d] close\n", peer_.get_handle()));

		// 尽量使用ID取消ACE_Event_Handler定时器, by sailzeng
		if (timer_id_)
		{
			reactor()->cancel_timer(timer_id_);
		}
		else
		{
			reactor()->cancel_timer(this);
		}

		peer_.close();
		return 0;
	}

	// 超时处理
	virtual int handle_timeout(const ACE_Time_Value& current_time,
		const void* act = 0)
	{
		if (current_time - last_proc_time_ >= timeout_time_)
		{
			ACE_DEBUG((LM_ERROR, "timeout, peer fd=%d\n", peer().get_handle()));
			// remove handler 会去调用handle_close(), 与返回-1效果一样
			reactor()->remove_handler(this, ACE_Event_Handler::READ_MASK);
		}

		return 0;
	}

	virtual ACE_HANDLE get_handle() const
	{
		return peer_.get_handle();
	}

	ACE_SOCK_Stream& peer()
	{
		return peer_;
	}

private:
	ACE_SOCK_Stream peer_;

	ACE_Time_Value last_proc_time_;
	ACE_Time_Value timeout_time_;
	long timer_id_;
	bool is_ok_;
};

// event_handler 包含一个ACE_Reactor
class EchoAcceptor : public ACE_Event_Handler
{
public:
	EchoAcceptor(ACE_Reactor* reactor = ACE_Reactor::instance(),
		ACE_Time_Value conn_timeout = ACE_Time_Value(60))
		: ACE_Event_Handler(reactor),
		conn_timeout_(conn_timeout) {}

	virtual ~EchoAcceptor()
	{

	}

	virtual int open(const ACE_INET_Addr& local)
	{
		if (0 != acceptor_.open(local, 1))
		{
			ACE_ERROR_RETURN((LM_ERROR, "acceptor open fail"), -1);
		}

		// 注册自己为反应器的accpet处理事件
		reactor()->register_handler(this, ACE_Event_Handler::ACCEPT_MASK);

		ACE_DEBUG((LM_ERROR, "server[%s:%d] listening...\n", local.get_host_addr(), local.get_port_number()));
		return 0;
	}

	// 相应accept事件,作为一个工厂,生成EchoEventHandler对象
	virtual int handle_input(ACE_HANDLE handle = ACE_INVALID_HANDLE)
	{
		EchoEventHandler* echo_hanndle = 0;
		ACE_NEW_RETURN(echo_hanndle, EchoEventHandler(reactor(), conn_timeout_), -1);

		if (-1 == acceptor_.accept(echo_hanndle->peer()))
		{
			ACE_DEBUG((LM_ERROR, "accept fail\n"));
			delete echo_hanndle;
			return -1;
		}

		if (0 != echo_hanndle->open())
		{
			ACE_DEBUG((LM_ERROR, "echo handler open fail\n"));
			echo_hanndle->close();
			return -1;
		}

		return 0;
	}

	virtual int handle_close(ACE_HANDLE handle = ACE_INVALID_HANDLE,
		ACE_Reactor_Mask close_mask = 0)
	{
		acceptor_.close();
		ACE_DEBUG((LM_ERROR, "accptor handle close, end reactor\n"));
		
		reactor()->end_reactor_event_loop();
		return 0;
	}

	virtual ACE_HANDLE get_handle() const
	{
		return acceptor_.get_handle();
	}

	// ACE_SOCK_Stream工厂
	ACE_SOCK_Acceptor acceptor_;

private:
	ACE_Time_Value conn_timeout_;
};

int ACE_TMAIN(int argc, ACE_TCHAR* argv[])
{
	EchoAcceptor* echosvr;
	ACE_Reactor reactor;
	ACE_NEW_RETURN(echosvr, EchoAcceptor(&reactor), -1);

	ACE_INET_Addr svraddr(LISTEN_PORT);
	echosvr->open(svraddr);

	if (0 != reactor.run_reactor_event_loop())
	{
		ACE_DEBUG((LM_ERROR, "run reactor event loop fail.\n"));
		return -1;
	}
	
	ACE_DEBUG((LM_ERROR, "event loop end.\n"));
	delete echosvr;
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值