基于ACE reactor_echo_server实现

来源:互联网 发布:华为云 和阿里云哪个好 编辑:程序博客网 时间:2024/05/22 15:04
/* * reactor_echo_server.cpp#include <ace/Event_Handler.h>#include <ace/SOCK_Stream.h>#include <ace/SOCK_Acceptor.h>#include <ace/Timer_Queue.h>#include <ace/Reactor.h>#include <ace/Log_Msg.h>#include <ace/Singleton.h>#include <ace/Dev_Poll_Reactor.h>#include <string>#include <map>typedef int (*CmdHandler)(const std::string& param, ACE_SOCK_Stream& sock);class CmdHandlers {public:bool registerCmdHandler(const std::string& cmd, CmdHandler h) {handlers.insert(std::make_pair(cmd, h));return true;}CmdHandler getCmdHandler(const std::string& cmd) {std::map<std::string, CmdHandler>::iterator i = handlers.find(cmd);return i != handlers.end() ? i->second : CmdHandler();}private:std::map<std::string, CmdHandler> handlers;};typedef ACE_Singleton<CmdHandlers, ACE_Null_Mutex> CmdHandlerInst;static const ACE_Time_Value MAX_INTERVAL(300);class Connection: public ACE_Event_Handler {public:Connection() {}~Connection() {ACE_DEBUG((LM_DEBUG, "~Connection()\n"));}int open(ACE_Reactor* react) {const char* welcome = "220 Welcome.\r\n";if (sock.send(welcome, ACE_OS::strlen(welcome)) == -1)ACE_ERROR_RETURN((LM_ERROR, "%p\n", "sock.send()"), -1);this->reactor(react);if (reactor()->schedule_timer(this, 0, ACE_Time_Value::zero,MAX_INTERVAL) == -1)ACE_ERROR_RETURN((LM_ERROR, "%p\n", "reactor().schedule_timer()"),-1);lastMsgTime = reactor()->timer_queue()->gettimeofday();return reactor()->register_handler(this, READ_MASK);}ACE_SOCK_Stream& socket() {return sock;}virtual ACE_HANDLE get_handle() const {return sock.get_handle();}virtual int handle_input(ACE_HANDLE fd) {ssize_t len = sock.recv(buf, sizeof buf);if (len <= 0) {if (len != 0)ACE_ERROR_RETURN((LM_ERROR, "%p\n", "sock.recv()"), -1);}lastMsgTime = reactor()->timer_queue()->gettimeofday();char* pos = ACE_OS::strstr(buf, "\r\n");if (pos)*pos = '\0';pos = ACE_OS::strchr(buf, ' ');std::string cmd, param;if (pos) {cmd = std::string(buf, pos);param = std::string(pos + 1);} elsecmd = buf;CmdHandler h = CmdHandlerInst::instance()->getCmdHandler(cmd);if (h)return h(param, sock);else {const char* reply = "500 FTP: command not recognized.\r\n";if (sock.send_n(reply, ACE_OS::strlen(reply)) == -1)ACE_ERROR_RETURN((LM_ERROR, "%p\n", "sock.send_n()"), -1);}//if (sock.send_n(buf, len) != len) {//ACE_ERROR((LM_ERROR, "%p\n", "sock.send_n()"));//return -1;//}return 0;}virtual int handle_timeout(const ACE_Time_Value ¤t_time,const void *act) {if (current_time - lastMsgTime > MAX_INTERVAL)reactor()->remove_handler(this, READ_MASK);return 0;}virtual int handle_close(ACE_HANDLE handle, ACE_Reactor_Mask close_mask) {if (handle == ACE_INVALID_HANDLE)return 0;//ACE_Reactor_Mask m = ALL_EVENTS_MASK | DONT_CALL;reactor()->cancel_timer(this);//reactor()->remove_handler(this, m);sock.close();delete this;return 0;}private:ACE_SOCK_Stream sock;char buf[512];ACE_Time_Value lastMsgTime;};// ----------------------------------------------------------------------------class Acceptor: public ACE_Event_Handler {public:Acceptor() {}~Acceptor() {ACE_DEBUG((LM_DEBUG, "~Acceptor()\n"));}int open(ACE_Reactor* react, unsigned short port) {this->reactor(react);ACE_INET_Addr addr;if (addr.set(port) == -1)ACE_ERROR_RETURN((LM_ERROR, "%p\n", "addr.set()"), -1);if (acceptor.open(addr, 1) == -1)ACE_ERROR_RETURN((LM_ERROR, "%p\n", "acceptor.open()"), -1);return reactor()->register_handler(this, ACCEPT_MASK);}virtual ACE_HANDLE get_handle() const {return acceptor.get_handle();}virtual int handle_input(ACE_HANDLE fd) {Connection* con = new Connection();if (acceptor.accept(con->socket()) == -1) {ACE_ERROR((LM_ERROR, "%p\n", "acceptor.accept()"));delete con;} else {if (con->open(reactor()) == -1)delete con;}return 0;}private:ACE_SOCK_Acceptor acceptor;};int main() {ACE_Reactor* r = new ACE_Reactor(new ACE_Dev_Poll_Reactor, true);ACE_Reactor::instance(r);Acceptor acceptor;if (acceptor.open(ACE_Reactor::instance(), 9988) == -1)return 1;return ACE_Reactor::instance()->run_reactor_event_loop();}// ----------------------------------------------------------------------------int handleCmdSYST(const std::string& param, ACE_SOCK_Stream& sock) {static const char* reply = "215 UNIX Type: L8\r\n";if (sock.send(reply, ACE_OS::strlen(reply)) == -1)ACE_ERROR_RETURN((LM_ERROR, "%p\n", "sock.send()"), -1);return 0;}bool a = CmdHandlerInst::instance()->registerCmdHandler("SYST", handleCmdSYST);

0 0
原创粉丝点击