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