ACE - 代碼層次及Socket封裝


原文出自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的優勢和便捷。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM