3 ACE_Reactor 同步框架 网络聊天室


3 ACE_Reactor 同步框架 网络聊天室



ACE_Reactor 框架


wKioL1hvE_njnXzAAAE4wHhCHmw308.png

wKiom1hvE_2jdI-AAAEqzfUjsEw886.png

wKioL1hvE_7QgbahAABdRdiiLUE295.png

wKioL1hvE_-wVyHQAALLP3UWcqI502.png





wKiom1hvE-bDzzxbAAKQFz6fcJo854.png




网络聊天室



wKiom1hvFM_wag5KAAPPqlh9pk0090.png

wKioL1hvFJfh30UUAAPPqlh9pk0007.png

wKiom1hvFJjgXLSLAAGROrkbEkY132.png





项目文件:



chunli@Linux:~/ace/AceChatRoom$tree
.
├──ChatMain.cpp
├──ChatRoom.cpp
├──ChatRoom.h
├──ParticipantAcceptor.cpp
├──ParticipantAcceptor.h
├──Participant.cpp
├──Participant.h
├──SignalHandler.cpp
└──SignalHandler.h

0directories,9files
chunli@Linux:~/ace/AceChatRoom$



主程序:

chunli@Linux:~/ace/AceChatRoom$catChatMain.cpp
#include<ace/Reactor.h>
#include"ParticipantAcceptor.h"
#include"SignalHandler.h"

intmain(){
SignalHandlersh;
ParticipantAcceptoracceptor;
ACE_INET_Addraddr(8868);
if(acceptor.open(addr)==-1)
return1;
returnACE_Reactor::instance()->run_reactor_event_loop();
}
chunli@Linux:~/ace/AceChatRoom$



ChatRoom类文件

chunli@Linux:~/ace/AceChatRoom$catChatRoom.h

#ifndefCHATROOM_H_
#defineCHATROOM_H_

#include<list>
#include<ace/Singleton.h>
#include<ace/Null_Mutex.h>

classParticipant;

classChatRoom{
public:
voidjoin(Participant*user);
voidleave(Participant*user);

voidforwardMsg(constchar*msg);

private:
std::list<Participant*>users;
};

//不加锁的方式
typedefACE_Singleton<ChatRoom,ACE_Null_Mutex>Room;

#endif/*CHATROOM_H_*/
chunli@Linux:~/ace/AceChatRoom$



chunli@Linux:~/ace/AceChatRoom$catChatRoom.cpp
#include<cstring>
#include<iostream>
#include"ChatRoom.h"
#include"Participant.h"
voidChatRoom::join(Participant*user)
{
	users.push_back(user);
}

voidChatRoom::leave(Participant*user)
{
	std::list<Participant*>::iteratorit=users.begin();
	for(;it!=users.end();++it)
	{
		if(*it==user)
		{
			users.erase(it);
			break;
		}
	}
}

voidChatRoom::forwardMsg(constchar*msg)
{
	std::list<Participant*>::const_iteratorit=users.begin();
	for(;it!=users.end();++it)
	{
		ACE_SOCK_Stream&sock=(*it)->socket();
		if(sock.send(msg,std::strlen(msg))==-1)
			(*it)->handle_close(ACE_INVALID_HANDLE,0);
	}
}
chunli@Linux:~/ace/AceChatRoom$







ParticipantAcceptor类文件

chunli@Linux:~/ace/AceChatRoom$catParticipantAcceptor.h
#ifndefPARTICIPANTACCEPTOR_H_
#definePARTICIPANTACCEPTOR_H_
#include<ace/Reactor.h>
#include<ace/Event_Handler.h>
#include<ace/SOCK_Acceptor.h>

classParticipantAcceptor:ACE_Event_Handler{
public:
ParticipantAcceptor(ACE_Reactor*reactor=ACE_Reactor::instance());
virtual~ParticipantAcceptor();

intopen(constACE_INET_Addr&addr);

virtualACE_HANDLEget_handle()const;
virtualinthandle_input(ACE_HANDLEh=ACE_INVALID_HANDLE);
virtualinthandle_close(ACE_HANDLEh,ACE_Reactor_MaskcloseMask);

private:
ACE_SOCK_Acceptoracceptor;
};

#endif/*PARTICIPANTACCEPTOR_H_*/
chunli@Linux:~/ace/AceChatRoom$
chunli@Linux:~/ace/AceChatRoom$
chunli@Linux:~/ace/AceChatRoom$catParticipantAcceptor.cpp
#include<ace/Log_Msg.h>
#include"ParticipantAcceptor.h"
#include"ChatRoom.h"
#include"Participant.h"

ParticipantAcceptor::ParticipantAcceptor(ACE_Reactor*reactor){
this->reactor(reactor);
}

ParticipantAcceptor::~ParticipantAcceptor(){
handle_close(ACE_INVALID_HANDLE,0);
}

intParticipantAcceptor::open(constACE_INET_Addr&addr){
if(acceptor.open(addr,0)==-1)
ACE_ERROR_RETURN((LM_ERROR,"%p\n","acceptor.open"),-1);

returnreactor()->register_handler(this,ACE_Event_Handler::ACCEPT_MASK);
}

ACE_HANDLEParticipantAcceptor::get_handle()const{
returnacceptor.get_handle();
}

intParticipantAcceptor::handle_input(ACE_HANDLEh){
Participant*user=newParticipant(reactor());

if(acceptor.accept(user->socket())==-1)
ACE_ERROR_RETURN((LM_ERROR,"acceptor.accept"),-1);

if(user->open()==-1){
ACE_ERROR_RETURN((LM_ERROR,-1);
user->handle_close(ACE_INVALID_HANDLE,0);
}else{
Room::instance()->join(user);
}

return0;
}

intParticipantAcceptor::handle_close(ACE_HANDLEh,ACE_Reactor_MaskcloseMask){
if(acceptor.get_handle()!=ACE_INVALID_HANDLE){
ACE_Reactor_Maskm=ACE_Event_Handler::ACCEPT_MASK
|ACE_Event_Handler::DONT_CALL;

reactor()->remove_handler(this,m);
acceptor.close();
}

return0;
}
chunli@Linux:~/ace/AceChatRoom$




Participant类文件

chunli@Linux:~/ace/AceChatRoom$catParticipant.h

#ifndefPARTICIPANT_H_
#definePARTICIPANT_H_

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

classParticipant:ACE_Event_Handler{
public:
staticACE_Time_ValuemaxMsgInterval;

Participant(ACE_Reactor*reactor=ACE_Reactor::instance());

intopen();

virtualACE_HANDLEget_handle()const;
virtualinthandle_input(ACE_HANDLEh=ACE_INVALID_HANDLE);
virtualinthandle_timeout(constACE_Time_Value&t,constvoid*=0);
virtualinthandle_close(ACE_HANDLEh,ACE_Reactor_MaskcloseMask);

ACE_SOCK_Stream&socket();

private:

ACE_Time_ValuelastMsgTime;
ACE_SOCK_Streamsock;
};

#endif/*PARTICIPANT_H_*/
chunli@Linux:~/ace/AceChatRoom$catParticipant.cpp
#include<ace/Log_Msg.h>
#include<ace/Timer_Queue.h>
#include"Participant.h"
#include"ChatRoom.h"

//ACE_Time_ValueParticipant::maxMsgInterval=ACE_Time_Value(5);
ACE_Time_ValueParticipant::maxMsgInterval=ACE_Time_Value(20);//20秒没有在聊天室说话的人,就被close

Participant::Participant(ACE_Reactor*reactor){
this->reactor(reactor);
}

intParticipant::open(){
lastMsgTime=reactor()->timer_queue()->gettimeofday();

intresult=
reactor()->register_handler(this,ACE_Event_Handler::READ_MASK);
if(result!=0)
returnresult;

result=reactor()->schedule_timer(this,ACE_Time_Value::zero,maxMsgInterval);
returnresult;

}

ACE_HANDLEParticipant::get_handle()const{
returnsock.get_handle();
}

intParticipant::handle_input(ACE_HANDLEh){
charbuf[512]="";
ssize_trecvBytes=sock.recv(buf,sizeof(buf));

if(recvBytes<=0)
ACE_ERROR_RETURN((LM_ERROR,"sock.recv"),-1);

lastMsgTime=reactor()->timer_queue()->gettimeofday();
Room::instance()->forwardMsg(buf);

return0;
}

intParticipant::handle_timeout(constACE_Time_Value&t,constvoid*){
if(t-lastMsgTime>maxMsgInterval)
reactor()->remove_handler(this,ACE_Event_Handler::READ_MASK);

return0;
}

intParticipant::handle_close(ACE_HANDLEh,ACE_Reactor_MaskcloseMask){
if(sock.get_handle()!=ACE_INVALID_HANDLE){
ACE_Reactor_Maskm=ACE_Event_Handler::ALL_EVENTS_MASK
|ACE_Event_Handler::DONT_CALL;

reactor()->cancel_timer(this);
reactor()->remove_handler(this,m);
sock.close();
Room::instance()->leave(this);
deletethis;
}

return0;
}

ACE_SOCK_Stream&Participant::socket(){
returnsock;
}
chunli@Linux:~/ace/AceChatRoom$


SignalHandler类文件

chunli@Linux:~/ace/AceChatRoom$catSignalHandler.h

#ifndefSIGNALHANDLER_H_
#defineSIGNALHANDLER_H_

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

classSignalHandler:ACE_Event_Handler{
public:
SignalHandler(ACE_Reactor*reactor=ACE_Reactor::instance());

virtualinthandle_signal(intsignum,siginfo_t*,ucontext_t*);
};

#endif/*SIGNALHANDLER_H_*/
chunli@Linux:~/ace/AceChatRoom$catSignalHandler.cpp
#include<ace/Log_Msg.h>
#include"SignalHandler.h"
#include"ChatRoom.h"

SignalHandler::SignalHandler(ACE_Reactor*reactor){
this->reactor(reactor);

ACE_Sig_Setsignals;
signals.fill_set();

this->reactor()->register_handler(signals,this);
}

intSignalHandler::handle_signal(intsignum,ucontext_t*){
switch(signum){
caseSIGINT:
ACE_DEBUG((LM_DEBUG,"signalSIGINT,butnotbeterminated!\n"));
break;
caseSIGUSR1:
ACE_DEBUG((LM_DEBUG,"signalSIGUSR1,broadcastgreeting...\n"));
Room::instance()->forwardMsg("helloeveryone!\n");
break;
caseSIGUSR2:
ACE_DEBUG((LM_DEBUG,"signalSIGUSR2,shutdownchatroom...\n"));
this->reactor()->end_reactor_event_loop();
break;
}
return0;
}
chunli@Linux:~/ace/AceChatRoom$


编译运行:

编译运行:
chunli@Linux:~/ace/AceChatRoom$g++*.cpp-lACE-Wall&&./a.out


3个客户端连接上来:
chunli@Linux:~$nclocalhost8868
1111111111111111111111
1111111111111111111111
222222222222222222222222
3333333333333333333333333333333
11111111111111111111111111111
11111111111111111111111111111
2222222222222222222222222222222
333333333333333333333333333333

chunli@Linux:~$nclocalhost8868
222222222222222222222222
222222222222222222222222
3333333333333333333333333333333
11111111111111111111111111111
2222222222222222222222222222222
2222222222222222222222222222222
333333333333333333333333333333
chunli@Linux:~$

chunli@Linux:~$nclocalhost8868
3333333333333333333333333333333
3333333333333333333333333333333
11111111111111111111111111111
2222222222222222222222222222222
333333333333333333333333333333
333333333333333333333333333333
chunli@Linux:~$


Ctrl+C杀不死
chunli@Linux:~/ace/AceChatRoom$g++*.cpp-lACE-Wall&&./a.out
^CsignalSIGINT,butnotbeterminated!

断开SSH终端:看到变成了守护进程
chunli@Linux:~$psaux|grepa.out
chunli29780.00.1227044208?S10:540:00./a.out

杀死服务程序:
chunli@Linux:~$psaux|grepa.out
chunli29520.00.0227042308pts/7S+10:500:00./a.out
chunli@Linux:~$kill-92952

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom