创建一个可正常结束的Proactor服务器

本文通过一个具体的ACE Proactor示例程序,展示了如何利用ACE库处理异步I/O操作,并改进程序使其能正常退出。

 

这是APG上关于Proactor使用的例子,去掉了trace信息,做了一点小修改:


#include <ace/Os_main.h>

#include <ace/Asynch_Acceptor.h>

#include <ace/Proactor.h>

#define LISTEN_PORT 5222


class HA_Proactive_Service : public ACE_Service_Handler

{

public:

       
~HA_Proactive_Service ()

       
{

             
if (this->handle () != ACE_INVALID_HANDLE)

                     ACE_OS
::closesocket (this->handle ());

       
}


       
virtual void open (ACE_HANDLE h, ACE_Message_Block&)

       
{

             
this->handle (h);

             
if (this->reader_.open (*this) != 0 || this->writer_.open (*this) != 0   )

             
{

                     
delete this;

                     
return;

             
}


             
ACE_Message_Block *mb;

              ACE_NEW_NORETURN
(mb, ACE_Message_Block (1024));

             
if (this->reader_.read (*mb, mb->space ()) != 0)

             
{

                     mb
->release ();

                     
delete this;

                     
return;

             
}

       
}


       
virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)

       
{

             
ACE_Message_Block &mb = result.message_block ();

             
if (!result.success () || result.bytes_transferred () == 0)

             
{

                     mb
.release ();

                     
delete this;

             
}

             
else

             
{

                     ACE_DEBUG
((LM_DEBUG, ACE_TEXT("Received Data : %c/n"), *mb.rd_ptr()));

                     mb
.release();


                     
ACE_Message_Block *new_mb;

                     ACE_NEW_NORETURN
(new_mb, ACE_Message_Block (1024));

                     
this->reader_.read (*new_mb, new_mb->space ());

             
}

       
}


       
virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result)

       
{ result.message_block ().release (); }


private:

       
ACE_Asynch_Read_Stream reader_;

       
ACE_Asynch_Write_Stream writer_;

};


class HA_Proactive_Acceptor : public ACE_Asynch_Acceptor<HA_Proactive_Service>

{

};


int ACE_TMAIN (int, ACE_TCHAR *[])

{

       
ACE_INET_Addr listen_addr( LISTEN_PORT );

       
HA_Proactive_Acceptor aio_acceptor;

       
if (0 != aio_acceptor.open (listen_addr, 0, 0, 5, 1, 0, 0))

              ACE_ERROR_RETURN
((LM_ERROR, ACE_TEXT ("%p/n"), ACE_TEXT ("acceptor open")), 1);


       
ACE_Proactor::instance ()->proactor_run_event_loop ();


       
return 0;

}


程序在5222端口上监听,对于每个已建立的连接,服务器将所有收到的数据打印到控制台上。这就是整个程序所实现的功能。

但是这个程序存在一个很大的问题:没有办法正常结束。当运行这个程序后,只能强制结束这个进程,因为程序没有提供从proactor事件循环中退出来的方法。

让程序能够正常退出是很有必要的,比如在进行内存泄漏的检测时,如果程序没有办法正常退出,那么内存泄漏的检测工作将很难进行。


为了实现能够正常关闭程序的目的,需要稍微修改一下上面的程序实现。

这次程序将会有两个线程在运行,一个是Proactor事件循环线程,另一个则为控制线程。在控制线程中,要能够关闭Proactor线程,然后将程序干净地退出。

得益于ACE强大的封装,所做的改动并不大:


class ProactorThread : public ACE_Task_Base

{

public:

       
int open()

       
{

             
return this->activate();

       
}


       
int close()

       
{

             
ACE_Proactor::instance()->proactor_end_event_loop();

             
this->wait();

             
return 0;

       
}


       
virtual int svc()

       
{

             
ACE_INET_Addr listen_addr( LISTEN_PORT );

             
HA_Proactive_Acceptor aio_acceptor;

             
if (0 != aio_acceptor.open (listen_addr, 0, 0, 5, 1, 0, 0))

                     ACE_ERROR_RETURN
((LM_ERROR, ACE_TEXT ("%p/n"), ACE_TEXT ("acceptor open")), 1);


             
ACE_Proactor::instance ()->proactor_run_event_loop ();

              ACE_DEBUG
((LM_DEBUG, ACE_TEXT("Thread ended/n")));


             
return 0;

       
}

};


int ACE_TMAIN (int, ACE_TCHAR *[])

{

       
ProactorThread thread;

       
thread.open();


       
int x;

       std
::cin >> x;


       
thread.close();


       
return 0;

}


仅仅只是添加了一个新的类,用于封装Proactor事件循环线程,另外修改了程序的主函数。这次程序将首先创建一个Proactor事件循环线程,然后主线程等待用户输入任意数后结束Proactor线程,在Proactor线程正常退出后主线程退出。


注意这里有两个要点:

1.当执行proactor_end_event_loop()之后,Proactor线程是从proactor_run_event_loop()处退出,所以会接着执行下面的代码,打印出” Thread ended”信息。

2.主线程必须使用wait()等待Proactor线程正常结束后再退出,否则如果主线程退出后,Proactor线程仍有一些资源释放工作未完成,那么就会存在资源未正确释放的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值