轉載於:http://www.cnblogs.com/TianFang/archive/2006/12/22/600191.htmlhtml
接受器-鏈接器設計模式(Acceptor-Connector)使分佈式系統中的鏈接創建及服務初始化與一旦服務初始化後所執行的處理去耦合。編程
這樣的去耦合經過三種組件來完成:acceptor、connector 和 servicehandler(服務處理器)。設計模式
結構服務器
1. 服務處理器(Service Handler):
Service Handler 實現應用服務,一般扮演客戶角色、服務器角色,或同時扮演這兩種角色。它提供掛鉤方法,由 Acceptor 或 Connector 調用,以在鏈接創建時啓用應用服務。此外,Service Handler 還提供數據模式傳輸端點,其中封裝了一個 I/O 句柄。一旦鏈接和初始化後,該端點被 Service Handler 用於與和其相連的對端交換數據。網絡
2. 接受器(Acceptor):
Acceptor 是一個工廠,實現用於被動地創建鏈接並初始化與其相關聯的 Service Handler 的策略。此外,Acceptor 包含有被動模式的傳輸端點工廠,它建立新的數據模式端點,由 Service Handler 用於在相連的對端間傳輸數據。經過將傳輸端點工廠綁定到網絡地址,好比 Acceptor 在其上偵聽的 TCP 端口號,Acceptor的 open 方法對該工廠進行初始化。
一旦初始化後,被動模式的傳輸端點工廠偵聽來自對端的鏈接請求。當鏈接請求到達時,Acceptor 建立 Service Handler,並使用它的傳輸端點工廠來將新鏈接接受進Service Handler 中。併發
3. 鏈接器(Connector):
Connector 是一個工廠,實現用於主動地創建鏈接並初始化與其相關聯的 Service Handler 的策略。它提供方法,由其發起到遠地 Acceptor 的鏈接。一樣地,它還提供另外一個方法,完成對 Service Handler 的啓用;該處理器的鏈接是被同步或異步地發起的。Connector 使用兩個分開的方法來透 明地支持異步鏈接創建。異步
4. 分派器(Dispatcher):
爲 Acceptor,Dispatcher 將在一或多個傳輸端點上接收到的鏈接請求多路分離給適當的 Acceptor。Dispatcher容許多個 Acceptor 向其登記,以偵聽同時在不一樣端口上從不一樣對端而來的鏈接。 爲 Connector,Dispatcher 處理異步發起的鏈接的完成。在這種狀況下,當異步鏈接被創建時,Dispatcher 回調 Connector。Dispatcher 容許多個 Service Handler 經過一個 Connector 來異步地發起和完成它們 的鏈接。注意對於同步鏈接創建,Dispatcher 並非必需的,由於發起鏈接的線程控制也完成服務服務處 理器的啓用。
Dispatcher 一般使用事件多路分離模式來實現,這些模式由反應器(Reactor)或前攝器(Proactor) 來提供,它們分別處理同步和異步的多路分離。一樣地,Dispatcher 也可使用主動對象(Active Obj ect)模式[5]來實現爲單獨的線程或進程。socket
協做分佈式
Acceptor 組件協做函數
Acceptor 和 Service Handler 之間的協做。這些協做被劃分爲三個階段:
1. 端點初始化階段:
爲被動地初始化鏈接,應用調用 Acceptor 的 open 方法。該方法建立被動模式的傳 輸端點,將其綁定到網絡地址,例如,本地主機的 IP 地址和 TCP 端口號,並隨後偵聽來自對端 Connector 的鏈接請求。其次,open 方法將 Acceptor 對象登記到 Dispatcher,以使分派器可以在鏈接事件 到達時回調 Acceptor。最後,應用發起 Dispatcher 的事件循環,等待鏈接請求從對端 Connector 到來。
2. 服務初始化階段:
當鏈接請求到達時,Dispatcher 回調 Acceptor 的accept 方法。該方法裝配如下活動 所必需的資源:
3. 服務處理階段:
在鏈接被動地創建和 Service Handler 被初始化後,服務處理階段開始了。在此階段, 應用級通訊協議,好比 HTTP 或 IIOP,被用於在本地 Service Handler 和與其相連的遠地 Peer 之間、 經由前者的 peer_stream_端點交換數據。當交換完成,可關閉鏈接和 Service Handler,並釋放資源。
Connector 組件協做
Connector 組件可使用同步和異步兩種方式來初始化它的 Service Handle,這裏僅介紹一下同步時的協做狀況。
同步的 Connector 狀況中的參與者之間的協做可被劃分爲如下三個階段:
實現
運行通常步驟:
主要角色:Service Handler(服務處理器)、Acceptor 和 Connector。
服務處理器:該抽象類繼承自 Event_Handler,併爲客戶、服務器或同時扮演兩種角色的組件所提供 的服務處理提供通用接口。應用必須經過繼承來定製此類,以執行特定類型的服務。Service Handler 接口以下所示:
1 template <class PEER_STREAM> 2 class Service_Handler : public Event_Handler 3 { 4 public: 5 //鏈接成功後的初始化入口函數 (子類定義). 6 virtual int open (void) = 0; 7 //返回通訊流的引用 8 PEER_STREAM &peer (void) 9 { 10 return peer_stream_; 11 } 12 };
一旦 Acceptor 或 Connector 創建了鏈接,它們調用 Service Handler 的 open 掛鉤。該純虛方法必須被 Concrete Service Handler 子類定義;後者執行服務特有的初始化和後續處理。
鏈接器:該抽象類實現主動鏈接創建和初始化 Service Handler 的通用策略。它的接口以下所示:
1 template <class SERVICE_HANDLER,class PEER_CONNECTOR> 2 class Connector : public Event_Handler 3 { 4 public: 5 enum Connect_Mode 6 { 7 SYNC, //以同步方式鏈接 8 ASYNC //以異步方式鏈接 9 }; 10 // 主動鏈接並激活服務處理器 11 int connect (SERVICE_HANDLER *sh, 12 const PEER_CONNECTOR::PEER_ADDR &addr, 13 Connect_Mode mode); 14 protected: 15 //定義鏈接激活策略 16 virtual int connect_service_handler(SERVICE_HANDLER *sh, 17 const PEER_CONNECTOR::PEER_ADDR &addr, 18 Connect_Mode mode); 19 // Defines the handler's concurrency strategy. 20 virtual int activate_service_handler(SERVICE_HANDLER *sh); 21 // 當以異步方式鏈接完成時激活服務處理器 22 virtual int complete (HANDLE handle); 23 private: 24 // IPC mechanism that establishes 25 // connections actively. 26 PEER_CONNECTOR connector_; 27 };
Conncetor 經過特定類型的 PEER CONNECTOR 和 SERVICE HANDLER 被參數化。PEER CONNECTO R 提供的傳輸機制被 Connector 用於主動地創建鏈接,或是同步地、或是異步地。SERVICE HANDLER提供的服務對與相連的對端交換的數據進行處理。C++參數化類型被用於使(1)鏈接創建策略與(2)服務處理器類型、網絡編程接口和傳輸層鏈接協議去耦合。
參數化類型是有助於提升可移植性的實現決策。例如,它們容許總體地替換 Connector 所用的 IPC 機 制。這使得 Connector 的鏈接創建代碼可在含有不一樣網絡編程接口(例如,有 socket,但沒有 TLI;反之 亦然)的平臺間進行移植。
Service Handler 的 open 掛鉤在鏈接成功創建時被調用。
接受器(Acceptor):該抽象類爲被動鏈接創建和初始化 Service Handler 實現通用的策略。Acceptor 的接 口以下所示:
1 template <class SERVICE_HANDLER, 2 class PEER_ACCEPTOR> 3 class Acceptor : public Event_Handler 4 { 5 public: 6 // Initialize local_addr transport endpoint factory 7 // and register with Initiation_Dispatcher Singleton. 8 virtual int open(const PEER_ACCEPTOR::PEER_ADDR &local_addr); 9 // Factory Method that creates, connects, and 10 // activates SERVICE_HANDLER's. 11 virtual int accept (void); 12 protected: 13 //定義服務處理器的建立策略 14 virtual SERVICE_HANDLER *make_service_handler (void); 15 // 定義服務處理器的鏈接策略 16 virtual int accept_service_handler(SERVICE_HANDLER *); 17 //定義服務處理器的激活策略 18 virtual int activate_service_handler(SERVICE_HANDLER *); 19 // Demultiplexing hooks inherited from Event_Handler, 20 // which is used by Initiation_Dispatcher for 21 // callbacks. 22 virtual HANDLE get_handle (void) const; 23 virtual int handle_close (void); 24 private: 25 // IPC mechanism that establishes 26 // connections passively. 27 PEER_ACCEPTOR peer_acceptor_; 28 };
Acceptor 經過特定類型的 PEER ACCEPTOR 和 SERVICE HANDLER 被參數化。PEER ACCEPTOR 提供的傳輸機制被 Acceptor 用於被動地創建鏈接。SERVICE HANDLER 提供的服務對與遠地對端交換的 數據進行處理。注意 SERVICE HANDLER 是由應用層提供的具體的服務處理器。
參數化類型使 Acceptor 的鏈接創建策略與服務處理器的類型、網絡編程接口及傳輸層鏈接發起協議去耦合。就如同 Connector 同樣,經過容許總體地替換 Acceptor 所用的機制,參數化類型的使用有助於提升可移植性。這使得鏈接創建代碼可在含有不一樣網絡編程接口(好比有 socket,但沒有 TLI;反之亦然)的平臺間移植。
make_service_handler 工廠方法定義 Acceptor 用於建立 SERVICE HANDLER 的缺省策略。以下所示:
1 template <class SH, class PA> SH * 2 Acceptor<SH, PA>::make_service_handler (void) 3 { 4 return new SH; 5 }
缺省行爲使用了"請求策略"(demand strategy),它爲每一個新鏈接建立新的 SERVICE HANDLER。可是, Acceptor 的子類能夠重定義這一策略,以使用其餘策略建立 SERVICE HANDLE,好比建立單獨的單體 (Singleton)[10]或從共享庫中動態連接 SERVICE HANDLER。
accept_service_handler 方法在下面定義 Acceptor 所用的 SERVICE HANDLER 鏈接接受策略:
1 template <class SH, class PA> int 2 Acceptor<SH, PA>::accept_service_handler(SH *handler) 3 { 4 peer_acceptor_->accept (handler->peer ()); 5 }
缺省行爲委託 PEER ACCEPTOR 所提供的 accept 方法。子類能夠重定義 accept_service_handler 方法,以 執行更爲複雜的行爲,好比驗證客戶的身份,以決定是接受仍是拒絕鏈接。
Activate_service_handler 定義 Acceptor 的 SERVICE HANDLER 併發策略:
程序示例:
在ACE中,默認的服務處理器是ACE_Svc_Handler,這也是一個模版類,能夠經過相關的參數特化。因爲ACE_Svc_Handler繼承自ACE_Task和ACE_Event_Handler,功能至關強大,同時也存在必定開銷,若是須要減少開銷能夠本身寫一個僅繼承自ACE_Event_Handler的服務處理器。
爲了演示簡單,我這裏就以一個EchoServer的服務器端和客戶端爲例,其中接收器和鏈接器都採用缺省策略,並無進行重載。
服務器端:
1 #include "ace/Reactor.h" 2 #include "ace/Svc_Handler.h" 3 #include "ace/Acceptor.h" 4 #include "ace/Synch.h" 5 #include "ace/SOCK_Acceptor.h" 6 7 class My_Svc_Handler; 8 typedef ACE_Acceptor<My_Svc_Handler,ACE_SOCK_ACCEPTOR> MyAcceptor; 9 10 class My_Svc_Handler: 11 public ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH> 12 { 13 public: 14 int open(void*) 15 { 16 ACE_OS::printf("\nConnection established\n"); 17 18 //註冊相應事件 19 ACE_Reactor::instance()->register_handler(this, 20 ACE_Event_Handler::READ_MASK); 21 return 0; 22 } 23 24 int handle_input(ACE_HANDLE) 25 { 26 int rev = peer().recv(data,1024); 27 if(rev == 0) 28 { 29 delete this; 30 } 31 else 32 { 33 data[rev]='\0'; 34 ACE_OS::printf("<<rev:\t %s\n",data); 35 peer().send(data,rev+1); 36 return 0; 37 } 38 } 39 private: 40 char data[1024]; 41 }; 42 int main(int argc, char* argv[]) 43 { 44 ACE_INET_Addr addr(3000); 45 MyAcceptor acceptor(addr,ACE_Reactor::instance()); 46 47 while(1) 48 ACE_Reactor::instance()->handle_events(); 49 } 50 51 客戶端: 52 53 #include "ace/Reactor.h" 54 #include "ace/Svc_Handler.h" 55 #include "ace/Connector.h" 56 #include "ace/Synch.h" 57 #include "ace/SOCK_Connector.h" 58 59 class My_Svc_Handler; 60 typedef ACE_Connector<My_Svc_Handler,ACE_SOCK_CONNECTOR> MyConnector; 61 62 class My_Svc_Handler: 63 public ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH> 64 { 65 public: 66 int open(void*) 67 { 68 ACE_OS::printf("\nConnection established\n"); 69 70 //註冊相應事件 71 ACE_Reactor::instance()->register_handler(this, 72 ACE_Event_Handler::READ_MASK); 73 return 0; 74 } 75 76 int handle_input(ACE_HANDLE) 77 { 78 int rev = peer().recv(data,1024); 79 if(rev == 0) 80 { 81 delete this; 82 } 83 else 84 { 85 data[rev]='\0'; 86 ACE_OS::printf("<<rev:\t %s\n",data); 87 return 0; 88 } 89 } 90 91 int sendData(char *msg) 92 { 93 ACE_OS::printf("<<send:\t %s\n",msg); 94 return peer().send(msg,strlen(msg)); 95 } 96 97 private: 98 char data[1024]; 99 }; 100 int main(int argc, char* argv[]) 101 { 102 ACE_INET_Addr addr(3000,"192.168.1.142"); 103 104 My_Svc_Handler *svchandler = new My_Svc_Handler(); 105 MyConnector connector; 106 107 if(connector.connect(svchandler,addr)==-1) 108 { 109 ACE_OS::printf("Connect fail"); 110 } 111 112 svchandler->sendData("hello wrold"); 113 114 while(1) 115 ACE_Reactor::instance()->handle_events(); 116 }