peakzhang 发表于 2007-12-11 22:07:55

连接-接入模式中每个对应client能不能新申请一个反应器?

在server端派生自ACE_Svc_Handler写对应Client的处理类ServerClient
有人说如果ServerClient开线程,因为默认ServerClient与ACE_Acceptor是同一个单体的反应器,所以在ServerClient线程中写的话就会出现分别在2个线程里读 写,于是需要同步访问ServerClient的sock_stream,
我的问题就是
确实需要同步吗?
假设需要同步,于是打算把ServerClient的读与写都放在自己的线程里:重载ServerClient的open函数重新申请一个反应器.
该怎么申请呢?
我简单尝试了一下在ServerClient中组合了一个反应器,但是在ServerClient的handler_close中delete this总是报错,似乎是新定义的反映器出错(我保证handler_close只被调用了一次)
完整的代码贴上,大家帮调试一下:
Server端:
#include <ace/Reactor.h>
#include <ace/Svc_Handler.h>
#include <ace/Acceptor.h>
#include <ace/sock_stream.h>
#include <ace/Acceptor.h>
#include <ace/SOCK_Acceptor.h>
#include <iostream>
using std::cout;
using std::endl;
class CSvcHandler :public ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH>
{
public:
CSvcHandler(void);
public:
~CSvcHandler(void);
public:
int handle_input(ACE_HANDLE);
int handle_close (ACE_HANDLE handle ,ACE_Reactor_Mask colse_mask);
int open(void*);
int svc();
private:
ACE_Reactor* m_pobjReactor;
    char data;
};
CSvcHandler::CSvcHandler(void)
{
cout<<"Acceptor ClientPoint:I'm coming.\n"<<endl;
m_pobjReactor = new ACE_Reactor();
}
CSvcHandler::~CSvcHandler(void)
{
cout<<"Acceptor ClientPoint:I'm out.\n";
delete m_pobjReactor;
}
int CSvcHandler::handle_input(ACE_HANDLE)
{
memset(data,0,sizeof(data));
int rev = peer().recv(data,sizeof(data) - 1);
if(rev < 1)
{
return -1;
}
else
{
cout<<"Acceptor ClientPoint recv:"<<data<<endl<<"and return:"<<data<<endl<<endl;
peer().send(data,sizeof(data) - 1);
return 0;
}
}
int CSvcHandler::handle_close (ACE_HANDLE handle ,ACE_Reactor_Mask colse_mask)
{
cout<<"Acceptor ClientPoint:handle_close\n";
delete this;
return 0;
}

int CSvcHandler:pen(void*)
{
reactor(m_pobjReactor);
m_pobjReactor->register_handler(this,ACE_Event_Handler::READ_MASK);
activate();
return 0;
}
int CSvcHandler::svc()
{
while(true)
{
m_pobjReactor->handle_events();
}
return 0;

}
int _tmain(int argc, _TCHAR* argv[])
{
ACE_INET_Addr l_objLocalAddr(3000,"127.0.0.1");
ACE_Acceptor<CSvcHandler,ACE_SOCK_ACCEPTOR> l_objAcceptor;
l_objAcceptor.open(l_objLocalAddr);
while(1)
{
ACE_Reactor::instance()->handle_events();
}
return 0;
}
_________________________________
Client端:
#include <ace/SOCK_Connector.h>
#include <ace/Connector.h>
#include <ace/Reactor.h>
#include <ace/Svc_Handler.h>
#include <ace/Acceptor.h"
#include <ace/sock_stream.h>
#include <iostream>
using std::cout;
using std::endl;
class CSvcHandler :public ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH>
{
public:
CSvcHandler(void);
public:
~CSvcHandler(void);
public:
int handle_input(ACE_HANDLE);
int handle_close (ACE_HANDLE handle ,ACE_Reactor_Mask colse_mask);
private:
    char data;
};

CSvcHandler::CSvcHandler(void)
{
cout<<"Connector ClientPoint:I'm coming.\n"<<endl;
}
CSvcHandler::~CSvcHandler(void)
{
cout<<"Connector ClientPoint: I'm out.\n";
}
int CSvcHandler::handle_input(ACE_HANDLE)
{
memset(data,0,sizeof(data));
int rev = peer().recv(data,sizeof(data) - 1);
if(rev < 1)
{
return -1;
}
else
{
cout<<"Connector ClientPoint recv:"<<data<<endl;
return 0;
}
}

int CSvcHandler::handle_close (ACE_HANDLE handle ,ACE_Reactor_Mask colse_mask)
{
cout<<"Connector ClientPoint:handle_close\n";
delete this;
return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
ACE_INET_Addr l_objRemoteAddr(3000,"127.0.0.1");
CSvcHandler* l_pobjClientPoint = new CSvcHandler();
ACE_Connector<CSvcHandler,ACE_SOCK_CONNECTOR> l_objConnector;
l_objConnector.connect(l_pobjClientPoint,l_objRemoteAddr);
char l_szBuffer = "C-A模式";
int l_nSize = l_pobjClientPoint->peer().send(l_szBuffer,sizeof(l_szBuffer));
cout<<"Connector ClientPoint send:"<<l_szBuffer<<endl;
while(true)               
{
ACE_Reactor::instance()->handle_events();
}
delete l_pobjClientPoint;
return 0;
}


[ 本帖最后由 peakzhang 于 2007-12-11 22:17 编辑 ]

peakzhang 发表于 2007-12-11 22:08:26

一堆问题:
你怎么确保在删除对象的时候,对象已经停止运行?

CSvcHandler::~CSvcHandler(void)
{
cout<<"Acceptor ClientPoint:I'm out.\n";
delete m_pobjReactor;

}


int CSvcHandler::svc()
{
while(true)
{
m_pobjReactor->handle_events(); //同步呢?
}

return 0;

}
你退出的时候,要删除m_pobjReactor,你怎么保证删除的时候,它已经停止运行了。

xjh_001 发表于 2007-12-12 16:54:03

ServerClient开线程的方式为:
1在open方法中调用activate方法启动多个处理线程.
2在handle_input方法中,将从网络接收到的数据调用put方法,加入到消息队列中
3在svc中,不停地getq,以取得接收到的消息,消息内容可以包括具体的接收数据,接收socket的句柄(便于向客户端发送应答数据)
4svc中接收到退出消息时,退出线程.因此在handle_close方法中,要发送n(激活的工作线程的个数)个退出消息,并调用wait方法,等待所有工作线程退出.
在这里,只是消息的处理是多线程的,数据的接收和发送用的是主线程的Reactor.
页: [1]
查看完整版本: 连接-接入模式中每个对应client能不能新申请一个反应器?