ACE之旅——Acceptor-Connector框架实例
来源:互联网 发布:卫生部 禁止网络看病 编辑:程序博客网 时间:2024/06/05 06:27
ACE的Reactor框架非常方便,结合Acceptor-Connector更为方便。以下是一个使用Acceptor-Connector框架写的daytime实例C/S应用。
#include "ace/INET_Addr.h"#include "ace/SOCK_Stream.h"#include "ace/SOCK_Acceptor.h"#include "ace/Log_Msg.h"#include "ace/Acceptor.h"#include "ace/Svc_Handler.h"#include <time.h>class ClientService;typedef ACE_Acceptor<ClientService, ACE_SOCK_ACCEPTOR> ClientAcceptor;class ClientService : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> { typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> super;public: int open(void *); virtual int handle_output(ACE_HANDLE fd = ACE_INVALID_HANDLE);};int ClientService::open(void *p) { if (super::open(p) == -1) return -1; ACE_TCHAR peer_name[MAXHOSTNAMELEN]; ACE_INET_Addr peer_addr; if (this->peer().get_remote_addr(peer_addr) == 0 && peer_addr.addr_to_string(peer_name, MAXHOSTNAMELEN) == 0) ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) Connection from %s\n"), peer_name)); return this->reactor()->register_handler(this, ACE_Event_Handler::WRITE_MASK);// return 0;}int ClientService::handle_output(ACE_HANDLE fd) { ACE_TCHAR peer_name[MAXHOSTNAMELEN]; ACE_INET_Addr peer_addr; this->peer().get_remote_addr(peer_addr); peer_addr.addr_to_string(peer_name, MAXHOSTNAMELEN); ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t) in ClientService::handle_output Connectionfrom %s\n"), peer_name)); time_t ticks = time(NULL); char timeBuf[128]; memset(timeBuf, 0, sizeof(timeBuf)); ACE_OS::snprintf(timeBuf, sizeof(timeBuf), "%.24s\r\n", ctime(&ticks)); ACE_OS::printf("output=[%s]\n", timeBuf); this->peer().send_n(timeBuf, ACE_OS::strlen(timeBuf)); this->reactor()->remove_handler(this, ACE_Event_Handler::NULL_MASK); return 0;}int ACE_TMAIN(int, ACE_TCHAR *[]) { ACE_INET_Addr port_to_listen("50000"); ClientAcceptor acceptor;// acceptor.reactor(ACE_Reactor::instance()); if (acceptor.open(port_to_listen) == -1) return 1; ACE_Reactor::instance()->run_reactor_event_loop(); return 0;}
- Acceptor-Connector框架大概的运行过程就是每个连接的客户端对应服务端一个ClientService对象,这个ClientService对象必须是从ACE_Svc_Handler派生的,当Acceptor接到连接请求并建立好该连接之后会创建ACE_Acceptor模板参数ClientService类的对象,并调用该对象的open方法,该方法默认只会添加READ事件到Reactor,需要监听WRITE事件,需要手动调用register_handler。
- 请注意带下划线的那行,因为daytime服务器没有从客户端接受任何输入,只是将信息发往客户端,所以如果只是简单的重写了handle_output方法,ACE_Reactor默认是用select实现的,水平触发的select会在短时间内多次出发WRITE事件,只要输出缓冲区未满,所以加下划线的那行的作用就是给客户端发送完后就让Reactor不再监听WRITE,并关闭该连接,即调用handle_close。当然这种方法在单线程情况下有效,如果多线程的情况应该需要加锁。
以下为daytime的客户端部分,ACE_Connector和ACE_Acceptor的运行过程类似
cli.cpp
#include "ace/INET_Addr.h"#include "ace/Connector.h"#include "ace/Log_Msg.h"#include "ace/Svc_Handler.h"#include "ace/SOCK_Connector.h"class Client : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> { typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> super;public: int handle_input(ACE_HANDLE);};int Client::handle_input(ACE_HANDLE fd) { int bc; char buf[64]; ACE_OS::memset(buf, 0, sizeof(buf)); bc = this->peer().recv(buf, sizeof(buf)); ACE_Reactor::instance()->end_reactor_event_loop(); write(1, buf, bc); return 0;}int ACE_TMAIN(int, ACE_TCHAR *[]) { ACE_INET_Addr svr(50000, ACE_LOCALHOST); ACE_Connector<Client, ACE_SOCK_CONNECTOR> connector; Client cli; Client *pc = &cli; if (connector.connect(pc, svr) == -1) ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("%p\n"), ACE_TEXT("connect")), 1); ACE_Reactor::instance()->run_reactor_event_loop(); return 0;}
- 在接受完数据后调用Reactor的end_reactor_event_loop方法,结束Reactor监听循环。
以下是编译这两个程序的makefile
CC= g++
INCL = $(ACE_ROOT)/include
LIBS = $(ACE_ROOT)/lib
reac_cli_deps = reac_cli.cpp
reac_svr_deps = reac_svr.cpp
.SUFFIXES: .cpp.o
.cpp.o:
$(CC) -g -I$(INCL) -c $*.cpp
all: reac_cli reac_svr
reac_cli: $(reac_cli_deps)
$(CC) -g -I$(INCL) -L$(LIBS) -o reac_cli $(reac_cli_deps) -lACE
reac_svr: $(reac_svr_deps)
$(CC) -g -I$(INCL) -L$(LIBS) -o reac_svr $(reac_svr_deps) -lACE
clean:
-rm *~
-rm reac_cli
-rm reac_svr
- ACE之旅——Acceptor-Connector框架实例
- ACE之Acceptor-Connector框架
- ACE之使用Acceptor-Connector框架
- ACE中Connector-Acceptor架构
- Acceptor-Connector
- ACE接受器-连接器设计模式Acceptor-Connector
- Acceptor-Connector模式系列
- 探究 ACE 的 Proactor_Test 示例中的 Acceptor 和 Connector 分别如何与 Proactor 关联。
- ACE的接受器(Acceptor)和连接器(Connector):连接建立模式
- ACE 前摄式Acceptor
- Socket接收器——Acceptor
- Acceptor-Connector模式一(Acceptor的工作)V2.0
- Bootstrap—后台框架Ace
- ACE Proactor框架使用实例
- 基于ACE应用编程框架——线程池 - [ACE]
- Tomcat学习之Acceptor
- Tomcat学习之Acceptor
- MongoDB——mongo-connector实例使用(for elasticsearch)
- hive使用经验
- IWindowManager.injectKeyEvent模拟按键
- 公司邮箱发送不出去,使用Outlook的SMTP发信认证设置
- Struts2的零配置和REST插件
- java设计模式之策略模式
- ACE之旅——Acceptor-Connector框架实例
- 看好ubuntu tablets
- Java反射机制
- vs 快捷键
- OCP原则
- 多线程:C#线程同步lock,Monitor,Mutex,同步事件和等待句柄(上)
- 创业北京全攻略:从零开始到开具第一张发票
- oracle 创建dblink
- 搜索android RAM ROM SD区别时找到一篇分析不错的文章