这两天在学习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;
}