原文出自http://www.cnblogs.com/binchen-china,禁止轉載。
ACE源碼約10萬行,是c++中非常大的一個網絡編程代碼庫,包含了網絡編程的邊邊角角。在實際使用時,並不是所有代碼都能用到你的項目中來,相反你只需要其中的一小部分就已經可以完成實際所需。
最近研究其源碼最大的感受就是代碼量大,資料少,邏輯跳躍大。網上搜了下ACE方面的書籍和資料,也是皮毛上打滾,概念滿天飛,側重講解如何使用其框架,復雜的底層代碼和實現都避而不談,不如直接看源碼來的直接。ACE代碼目錄結構並不是非常好,很多文件堆在一個路徑下面,很閱讀難歸納各個文件的功能,源碼大量使用模板和導入導出,source insight看的實在汗顏。
ACE代碼可以分三個層次:OS層、OO層和框架層:
- OS層主要是為了兼容各個平台,將網絡底層API統一化,這一層用戶往往不用關心。
- OO層則是對一些常用的數據結構或方法進行OO封裝,方便上層使用,包括socket方法,進程、線程和他們的同步機制等。
- 框架層實現了一些優秀的網絡框架,直接拿來用就好了。
OO層經常用到的就是Socket封裝,這部分內容主要包括以下幾個:
- ACE_SOCK_Connector:連接器,主動建立連接,用於Socket Client。
- ACE_SOCK_Acceptor:接受器,被動建立連接,用於Socket Server。
- ACE_SOCK_Stream:傳輸數據的流,用於傳輸數據。
- ACE_INET_Addr:用於表示通信端點的地址。
封裝這四個結構簡化了Socket編程代碼,避免了代碼細節上錯誤,也增強了移植性和面向對象思想的應用。
之前文章的服務器編程可以看做是純C語言的面向過程編程,從bind到listen等,非常繁瑣且參數復雜,調用易出錯,異常處理容易遺漏等,ACE的這四個Socket封裝把這些問題都解決了。所有細節代碼都在ACE內部屏蔽了。
下面直接上服務器代碼:
1 #include <ace/INET_Addr.h> 2 #include <ace/SOCK_Acceptor.h> 3 #include <ace/SOCK_Stream.h> 4 #include <ace/Log_Msg.h> 5 6 #define MAX_BUFF_SIZE 1024 7 #define LISTEN_PORT 5010 8 #define SERVER_IP ACE_LOCALHOST 9 10 class Server 11 { 12 public: 13 Server(int port,char* ip); 14 ~Server(); 15 bool open(); 16 bool run(); 17 void close(); 18 ACE_SOCK_Stream& Getstream(){return Svr_stream;} 19 private: 20 ACE_INET_Addr Svr_addr,Cli_addr; 21 ACE_SOCK_Acceptor Svr_aceept; 22 ACE_SOCK_Stream Svr_stream; 23 }; 24 25 Server::Server(int port,char* ip):Svr_addr(port,ip) 26 { 27 28 } 29 30 Server::~Server() 31 { 32 33 } 34 35 bool Server::open() 36 { 37 if (-1 == Svr_aceept.open(Svr_addr,1)) 38 { 39 ACE_DEBUG((LM_ERROR,ACE_TEXT("failed to accept\n"))); 40 Svr_aceept.close(); 41 return false; 42 } 43 return true; 44 } 45 46 bool Server::run() 47 { 48 if (-1 == Svr_aceept.accept(Svr_stream,&Cli_addr)) 49 { 50 ACE_DEBUG((LM_ERROR,ACE_TEXT("failed to accept\n"))); 51 Svr_aceept.close(); 52 return false; 53 } 54 return true; 55 } 56 57 void Server::close() 58 { 59 Svr_aceept.close(); 60 } 61 62 int main() 63 { 64 Server Svr(LISTEN_PORT,(char*)SERVER_IP); 65 char strBuffer[MAX_BUFF_SIZE]; 66 67 if (!Svr.open()) 68 { 69 return 0; 70 } 71 ACE_DEBUG((LM_INFO, ACE_TEXT("open success!\n"))); 72 73 if (!Svr.run()) 74 { 75 return 0; 76 } 77 ACE_DEBUG((LM_INFO, ACE_TEXT("run success!\n"))); 78 79 ACE_SOCK_Stream Svr_data = Svr.Getstream(); 80 81 while(1) 82 { 83 int byte = Svr_data.recv(strBuffer,MAX_BUFF_SIZE); 84 if (-1 == byte) 85 { 86 ACE_DEBUG((LM_INFO, ACE_TEXT("receive data failed\n"))); 87 break; 88 } 89 else if(0 == byte) 90 { 91 ACE_DEBUG((LM_INFO, ACE_TEXT("client closed!\n"))); 92 break; 93 } 94 else 95 { 96 ACE_DEBUG((LM_INFO, ACE_TEXT("receive from client: %s\n"),strBuffer)); 97 ACE_OS::memset(strBuffer, 0, sizeof(strBuffer)); 98 } 99 } 100 Svr_data.close(); 101 Svr.close(); 102 return 0; 103 }
運行結果:
至此,還並沒有發現ACE完成的Server和之前用linux底層API完成的代碼或功能上有何區別。這里還暫時只是單純的利用OO層代碼熟悉ACE,后續將利用ACE的Reactor框架進行Server開發。感受ACE的優勢和便捷。