关于ACE到问题
我目前是在linux下用ACE开发一个关于TCP的通道模块,运用了ACE_Reactor的Accetpor-Connector框架,其中实现了一个服务处理器,ChannelSvcHandler,现将我到代码贴下class ChannelSvcHandler : public ACE_Svc_Handler<ACE_SOCK_STREAM,ACE_MT_SYNCH> {
typedef ACE_Svc_Handler<ACE_SOCK_STREAM,ACE_MT_SYNCH> PARENT;
public:
ChannelSvcHandler();
virtual ~ChannelSvcHandler();
public:
//打开服务处理器
virtual int open (void *p);
//接收处理函数
virtual int handle_input (ACE_HANDLE fd);
//数据发送线程
virtual int svc();
//退出线程并关闭连接
int QuitSvcAndClose(bool bupdate = true);
private:
//通道连接器指针
ChannelConnector * pConnector_;
};
int ChannelSvcHandler:pen(void *p) {
//调用父类函数,完成向反应器注册
PARENT:pen();
//保存通道连接器指针
if (0 != p) {
pConnector_ = reinterpret_cast<ChannelConnector *>(p);
}
//激活数据发送线程
this->activate();
return 0;
}
int ChannelSvcHandler::handle_input(ACE_HANDLE fd) {
//创建接收缓存
ACE_Message_Block *mbk = 0;
ACE_NEW_RETURN(mbk,ACE_Message_Block(DEFAULT_BLOCK_SIZE),0);
//接收数据
ssize_t count = this->peer().recv(mbk->wr_ptr(),mbk->size());
if (count > 0) {
//接收成功,移动写指针
mbk->wr_ptr(count);
//返回接收数据
if (!pConnector_->utReceiveMessage(mbk)) {
mbk->release();
ACE_ERROR((LM_ERROR,ACE_TEXT("接收数据返回失败!\n")));
}
} else {
//接收失败,表示对端关闭或网络异常
mbk->release();
ACE_DEBUG((LM_DEBUG,ACE_TEXT("连接异常,将断开与对端到连接!\n")));
//退出线程并关闭连接
QuitSvcAndClose();
}
return 0;
}
int ChannelSvcHandler::svc() {
ACE_Message_Block *mbk;
while (1) {
//从队列获取数据
if (-1 != this->getq(mbk)) {
//判断是否为退出消息
if (mbk->size() == 0 && mbk->msg_type() == ACE_Message_Block::MB_STOP) {
//是则跳出循环,退出线程,关闭连接
mbk->release();
msg_queue()->close();
ACE_DEBUG((LM_DEBUG,ACE_TEXT("收到退出消息,数据发送线程退出,并断开连接!\n")));
break;
} else {
//否则为需发送到数据
while (mbk->length() > 0) {
//发送数据到对端
ssize_t count = this->peer().send(mbk->rd_ptr(),mbk->length());
if (count > 0) {
//发送成功,移动读指针
mbk->rd_ptr(count);
} else {
//发送失败,表示网络异常,直接跳出,等待接收处理函数处理
break;
}
}
//发送完毕后释放资源
mbk->release();
}
}
}
return 0;
}
int ChannelSvcHandler:uitSvcAndClose(bool bupdate) {
//判断是否需要更新通道连接器中到服务处理器指针
if (bupdate) {
pConnector_->UpdateSvcHandler();
}
//构造退出消息
ACE_Message_Block *quit_msg = 0;
ACE_NEW_RETURN(quit_msg,ACE_Message_Block(0,ACE_Message_Block::MB_STOP),0);
//放入队列头
if (-1 == this->ungetq(quit_msg)) {
ACE_ERROR_RETURN((LM_ERROR,ACE_TEXT("退出消息压入队列失败!\n")),0);
}
//等待数据发送线程退出
this->wait();
return 1;
}
现 在将问题具体说说,如果因为某种原因或主动关闭程序,从程序主线程中调用QuitSvcAndClose,该服务处理器可正常关闭;如果所对端关闭或网络 异常等原因,导致handle_input中接收到的数据为0,这时我也会调用QuitSvcAndClose来先关闭线程,进而关闭服务处理器,但这时 候QuitSvcAndClose中到this->wait就一直不返回阻塞在那,svc线程中的 ACE_DEBUG((LM_DEBUG,ACE_TEXT("收到退出消息,数据发送线程退出,并断开连接!\n")))这条日志已经打印,表示线程已 退出,为什么会不返回呢,不知道我在handle_input中调用这样到这样到退出线程到函数再等待线程退出是否合适????
后来我想直接把 open函数中的activate参数设成THR_DETACHED,然后QuitSvcAndClose中不掉用wait直接返回,程序没有阻塞正常运 行了,但通过打印到信息可以看出,hande_input函数貌似被调用了N次,这是我最搞不懂到地方!!!至于开启到线程到底是该设成 THR_DETACHED还算THR_JOINABLE,两者到区别除了一个所系统自动回收资源,另一个是需要wait才能回收外,还有啥区别,我们该如 何选择呢???