使用ACE中的Proactor的話,會要比我們使用我們直接寫的要來得簡單。
在說Proactor之前我們需要了解Windows裏的完成端口的工作原理。
完成端口是WinNT內核裏的一個框架。我們可以爲我們的一些異步的操作
新建一個完成端口,然後這個完成端口會有幾個工作線程來處理。我們
可以將socket,或是一個文件讀寫,或是一個串口的收發數據的句柄,
梆定到這個完成端口之上,當一個讀或是寫的事件完成之後,完成端口
機制將會自動將一個完成消息放到完成隊列中,完成端口的工作線程池
將會被觸發調用。回調的時候我們梆定時將一些基礎的信息也梆在其中,
當工作線程也會通過一種叫做完成項的指針返回給你。就是說,你可能
梆定了多個socket或是文件都是沒有問題的。按微軟人寫的文檔裏說的
可以面對百萬個這樣的異步對象。
這裏我就不再使用WinAPI寫完成端口了。
現在是使用ACE框架來寫一個。
使用他來做一個完成端口步驟也是一樣的。
開始的時候需要一個完成端口,還有完成端口的工作線程池。在ACE框架
裏提供了一種叫ACE_Task的線程池模塊類
和一般的線程類一樣,它的工作時調用的函數是
virtual int svc (void);
只是如何使用呢。無非是開啓線程與關閉線程兩個操作。
在此類中定義一個ACE_Thread_Semaphore sem_;變量
然後開戶n個線程的過程就是這樣的:
int Proactor_Task::star(int nMax)
{
...
this->activate (THR_NEW_LWP, nMax);
for (;nMax>0;nMax--)
{
sem_.acquire();
}
return 0;
}
一個是創建,二個是一個一個的觸發。讓這一些線程都工作.
當然工作線程都要釋放自己:
int Proactor_Task::svc()
{
ACE_DEBUG((LM_INFO,ACE_TEXT("svc函數調用!/n")));
sem_.release(1);
...
return 0;
}
好了。這個線程池開始工作了。接下來,我們要做將完成端口對象給創建出來:
在這個線程池裏定義一個完成端口對象指針:
ACE_Proactor * proactor_;
創建的過程是這樣的。
//是在Win32下,就使用這個Proactor的實現
ACE_WIN32_Proactor *proactor_impl = new ACE_WIN32_Proactor(); //新建proactor的實現
proactor_=new ACE_Proactor(proactor_impl,1); //與proactor關聯
ACE_Proactor::instance (this->proactor_, 1); //將新建出來的proactor保存在靜態框架裏
如何刪除呢。
ACE_Proactor::end_event_loop();
this->wait();
之後來寫線程池裏的函數
ACE_Proactor::run_event_loop();
只要寫一句就OK了。
這就完成了一個完成端口對象的創建過程。我們只要做一下封裝就OK了。
給它一個工作線程的大小。之後它就會自動的新建一個完成端口在ACE_Proactor::instance裏。
接下來我們要做Acceptor與recv。
實計上ACE裏已經爲我們寫好了。它們就是:
ACE_Asynch_Acceptor類ACE_Service_Handler類
class Accepte : public ACE_Asynch_Acceptor<Receive>
class Receive : public ACE_Service_Handler
這樣一繼承,工作就已經完成了。
如果我們想得到這一些網絡事件的話,可以做一些繼承就OK了。
他們內部調用的過程是這樣的:
當有一個新的用戶連接上來之後。
Accepte會有一個函數回調。
virtual HANDLER *make_handler (void);
這個函數裏,我們必需寫一個new Receive對象。
new完成之後Receive的open函數將會回調
open函數調用的時候,此接收對象的socket句柄就得到了。我們就在這個時候需要將一個
讀、寫的流梆定在其中。還有就是做一步異步的接收數據。這個如果你寫過重疊方式的話就會
比較的瞭解,這也叫做異步的I/O的投遞。等這個recv完成之後就會回調。
好了。這就算完成了。現在把代碼貼出來。
我不知道如何做一個下載點。不好意思只有大家自己複製下來
我使用的VC6.0,ACE5.4.1的編程環境
// Accepte.h: interface for the Accepte class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_ACCEPTE_H__DCEC809D_E5D2_48D1_A8A7_C9FD3C4D7C15__INCLUDED_)
#define AFX_ACCEPTE_H__DCEC809D_E5D2_48D1_A8A7_C9FD3C4D7C15__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <ace/Asynch_Acceptor.h>
#include "Receive.h"
class Accepte : public ACE_Asynch_Acceptor<Receive>
{
public:
Receive* make_handler (void);
Accepte();
virtual ~Accepte();
};
#endif // !defined(AFX_ACCEPTE_H__DCEC809D_E5D2_48D1_A8A7_C9FD3C4D7C15__INCLUDED_)
// Accepte.cpp: implementation of the Accepte class.
//
//////////////////////////////////////////////////////////////////////
#include "Accepte.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Accepte::Accepte()
{
}
Accepte::~Accepte()
{
}
Receive* Accepte::make_handler(void)
{
return new Receive();
}
// Proactor_Task.h: interface for the Proactor_Task class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_PROACTOR_TASK_H__12F37C95_9872_4923_89A2_5A59AE7AC1FD__INCLUDED_)
#define AFX_PROACTOR_TASK_H__12F37C95_9872_4923_89A2_5A59AE7AC1FD__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "ace/Task_T.h"
#include "ace/Thread_Semaphore.h"
#include "ace/Proactor.h"
#include "ace/WIN32_Proactor.h"
class Proactor_Task : public ACE_Task<ACE_MT_SYNCH>
{
public:
Proactor_Task();
virtual ~Proactor_Task();
int star(int nMax);
int stop();
virtual int svc (void);
int create_proactor();
int release_proactor();
ACE_Thread_Semaphore sem_;
ACE_Proactor * proactor_;
};
#endif // !defined(AFX_PROACTOR_TASK_H__12F37C95_9872_4923_89A2_5A59AE7AC1FD__INCLUDED_)
// Proactor_Task.cpp: implementation of the Proactor_Task class.
//
//////////////////////////////////////////////////////////////////////
#include "Proactor_Task.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Proactor_Task::Proactor_Task()
{
}
Proactor_Task::~Proactor_Task()
{
}
int Proactor_Task::star(int nMax)
{
create_proactor();
this->activate (THR_NEW_LWP, nMax);
for (;nMax>0;nMax--)
{
sem_.acquire();
}
return 0;
}
int Proactor_Task::stop()
{
ACE_Proactor::end_event_loop();
this->wait();
return 0;
}
int Proactor_Task::release_proactor()
{
ACE_Proactor::close_singleton ();
proactor_ = 0;
return 0;
}
int Proactor_Task::create_proactor()
{
ACE_WIN32_Proactor *proactor_impl = 0;
ACE_NEW_RETURN (proactor_impl,
ACE_WIN32_Proactor,
-1);
// always delete implementation 1 , not !(proactor_impl == 0)
ACE_NEW_RETURN (this->proactor_,
ACE_Proactor (proactor_impl, 1 ),
-1);
// Set new singleton and delete it in close_singleton()
ACE_Proactor::instance (this->proactor_, 1);
return 0;
}
int Proactor_Task::svc()
{
ACE_DEBUG((LM_INFO,ACE_TEXT("svc函數調用!/n")));
sem_.release(1);
ACE_Proactor::run_event_loop();
return 0;
}
// Receive.h: interface for the Receive class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_RECEIVE_H__0E7EF8C0_465F_4D9C_8A29_0C2A0F1EAFFE__INCLUDED_)
#define AFX_RECEIVE_H__0E7EF8C0_465F_4D9C_8A29_0C2A0F1EAFFE__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <ace/Asynch_io.h>
#include <ace/Message_Block.h>
#include <ace/Log_Msg.h>
#include <ace/OS_Memory.h>
class Receive : public ACE_Service_Handler
{
public:
Receive();
virtual ~Receive()
{
if (this->handle() != ACE_INVALID_HANDLE )
{
closesocket(SOCKET(this->handle()));
}
}
virtual void open(ACE_HANDLE h,ACE_Message_Block& );
virtual void handle_read_stream(const ACE_Asynch_Read_Stream::Result &result);
virtual void handle_write_stream(const ACE_Asynch_Write_Stream::Result &result);
private:
ACE_Asynch_Write_Stream write_;
ACE_Asynch_Read_Stream reader_;
};
#endif // !defined(AFX_RECEIVE_H__0E7EF8C0_465F_4D9C_8A29_0C2A0F1EAFFE__INCLUDED_)
// Receive.cpp: implementation of the Receive class.
//
//////////////////////////////////////////////////////////////////////
#include "Receive.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Receive::Receive()
{
}
void Receive::open(ACE_HANDLE h,ACE_Message_Block& )
{
this->handle(h);
if (this->write_.open(*this)!=0 ||
this->reader_.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)
{
ACE_ERROR((LM_ERROR,ACE_TEXT(" (%t) error information %p.")));
mb->release();
delete this;
return;
}
}
void Receive::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_Message_Block* new_mb;
ACE_NEW_NORETURN(new_mb,ACE_Message_Block(1024));
this->reader_.read(*new_mb,new_mb->space());
}
return ;
}
void Receive::handle_write_stream (const ACE_Asynch_Write_Stream::Result &result)
{
result.message_block().release();
return ;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//main.cpp
#ifdef _DEBUG
#pragma comment(lib,"aced")
#else
#pragma comment(lib,"ace")
#endif
#include <ace/ace.h>
#include "Accepte.h"
#include "Proactor_Task.h"
int ACE_TMAIN(int ,char*[])
{
Proactor_Task task;
task.star(3);
Accepte accepte;
accepte.open(ACE_INET_Addr (2222), 0, 1,ACE_DEFAULT_BACKLOG,1,ACE_Proactor::instance());
int nExit=0;
while (nExit==0)
scanf("%d",&nExit);
return 0;
}