ACE - 代码层次及Socket封装
Posted 白驹过隙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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的优势和便捷。
以上是关于ACE - 代码层次及Socket封装的主要内容,如果未能解决你的问题,请参考以下文章
VSCode自定义代码片段14——Vue的axios网络请求封装
VSCode自定义代码片段14——Vue的axios网络请求封装