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的优势和便捷。

时间: 2024-08-17 15:28:28

ACE - 代码层次及Socket封装的相关文章

C# .NET Socket封装

Socket封装,支持多客户端. 封装所要达到的效果,是可以像下面这样使用Socket和服务端通信,调用服务端的方法: DemoService demoService = new DemoService(); DemoService2 demoService2 = new DemoService2(); string result = demoService.Test("测试DemoService", 1); demoService.Test2("测试DemoService&

Linux C socket 封装

/************************************************************************** * Linux C socket 封装 * 声明: * 同样的代码当然没必要敲很多遍了,一遍就够了,封起来,什么时候要用, * 什么时候就来这里拿. * * 2015-7-4 晴 深圳 南山平山村 曾剑锋 ***********************************************************************

Socket封装之聊天程序(二)

今天,学习一下socket的封装. 类图 ??首先,我们把需要封装的各个类初步的设计如下: ??接下来,我们建立类与类之间的关系:??其中,CStream类可有可无,这个类是用来封装各种读写流的. socket封装 stream类 stream.h: class CStream { public: CStream(int fd = -1); ~CStream(); void SetFd(int fd); int GetFd(); int Read(char *buf, int count); /

Socket封装之聊天程序(三)

  今天,完成一下epoll的封装. 类图   首先,还是画下类图,初步设计一下.  具体函数,我们下面详解. epoll封装 EpollBase类 CEpollBase.h: class CEpollBase { public: CEpollBase(int max_events); virtual ~CEpollBase(); bool Create(int size); bool AddEvent(int fd,int events); bool ModEvent(int fd,int e

iphone使用开源代码Asyncsocket进行socket编程

iphone的标准推荐CFNetwork C库编程.但是编程比较烦躁.在其它OS往往用类来封装的对Socket函数的处理.比如MFC的CAsysncSocket.在iphone也有类似于开源项目.cocoa AsyncSocket库, 官方网站:http://code.google.com/p/cocoaasyncsocket/;它用来简化CFnetwork的调用. 一.在项目引入ASyncSocket库 1.下载ASyncSocket库源码 2.把ASyncSocket库源码加入项目:只需要增

web前端socket封装库--giraffe

摘要: 最近在做前端的socket消息推送,使用了socket.io.js的最新版本.使用过的都知道socket.io.js是基于消息类型来通信的,如果消息类型多了就很难维护.所以本人就对socket.io.js进行了应用层的封装.命名为giraffe.js,giraffe的含义是长颈鹿,意为能够望的远. 源码:https://github.com/baixuexiyang/Giraffe      欢迎fork和star 使用: giraffe.js同时支持AMD和CMD以及node.js环境

ACE代码编辑器,代码提示,添加自定义数据

//设置自动提示代码 var setCompleteData = function(data) { var langTools = ace.require("ace/ext/language_tools"); langTools.addCompleter({ getCompletions: function(editor, session, pos, prefix, callback) { if (prefix.length === 0) { return callback(null,

代码改变世界 | 如何封装一个简单的 Koa

下面给大家带来:封装一个简单的 KoaKoa 是基于 Node.js 平台的下一代 web 开发框架Koa 是一个新的 web 框架,可以快速而愉快地编写服务端应用程序,本文将跟大家一起学习:封装一个简单的 Koa一个简单的 http 服务使用 node 提供的 http 模块,可以很容易的实现一个基本的 http 服务器,新建一个 application.js 文件,内容如下: const http = require('http') const server = http.createSer

飘逸的python - 使用dis模块进行代码层次的性能剖析

dis - Disassembler for Python bytecode,即把python代码反汇编为字节码指令. 使用超级简单:python -m dis xxx.py 当我在网上看到while 1比while True快的时候,我感到很困惑,为何会有这种区别呢? 于是使用dis来深入. 假设est_while.py代码如下. #coding=utf-8 while 1: pass while True: pass 下面是使用dis来进行剖析. E:\>python -m dis test