ACE Socket Wrapper Facade

1:Socket API

1.1 IPC(进程间通信)

  IPC分为本地IPC(同一计算机上的不同进程)和远程IPC(网络互联的不同计算机),本地IPC的机制有共享内存(shared memory)、管道(pipe)、信号(signal)等,远程IPC的机制有Socket、X25电路、WIN32命名管道(named pipe)。

1.2 Socket API

  应用程序可以用Socket API中的C函数创建、管理本地通信端点(endpoint),即socket套接字。一个socket可以通过一个handle访问。在windows中,socket句柄和其他I\O句柄不能互换。

  Socket API包含20多个系统函数,这些函数分为以下5类:

  从服务类型(stream流、datagram数据报)、连接角色(active connection establishment主动连接端,常作为client;passive connection establishment被动连接端,常作为server)、通信领域(local or remote)几个方面,对socket api进行分组,得到socket空间分布图:

1.3 Socket API局限

  原始Socket API有以下几个局限性:容易出错、复杂、不可移植。C++ Network Program v1的2.3.1节指出socket api的数个问题。比如,sockaddr_in变量必须手动初始化,必须用htons将“主机字节顺序转换为网络字节顺序”,服务端必须按照顺序写入bind、linsten、accept,缺乏命名规范等。

2 ACE Socket Wrapper Facade

  ACE定义了一组C++类,用来解决第一节提到的Socket API局限性,ACE Socket Wrapper Facade提供的ACE类有:

  这些ACE类的UML关系图如下:

 

  按照1.2节分类维度,将这些ACE类组合分层成如下空间图。

2.1 ACE Socket地址簇:ACE_Addr和ACE_INET_Addr

  头文件“ace/Addr.h”和“ace/INET_Addr.h”。

  ACE_Addr和ACE_INET_Addr的构造函数实现了对通用地址的封装,避免了手动分配sockaddr_in的麻烦工作。ACE_Addr和ACE_INET_Addr的类图如下所示:

  ACE_INET_Addr内部封装了sockaddr_in,其构造函数内部会先调用reset清空sockaddr_in,然后调用set为sockaddr_in赋值。此外,ACE_Addr类还有一个static成员函数sap_any,可用作系统随机分配端口号。ACE_INET_Addr的一个例子为:

ACE_INET_Addr      lAddr(atoi(port.c_str()),ip.c_str());

2.2 ACE Socket机制

2.2.1 ACE_IPC_SAP

  头文件“ace/IPC_SAP.h”

  ACE_IPC_SAP是ACE IPC wrapper facade的根节点,为其他ACE wrapper facade提供了基本的"I\O句柄"操作能力。此外,ACE_IPC_SAP是一个抽象类,其构造函数声明在类的protected内,外部无法实例化。其主要方法为:

  enable和disable成对出现,用于启动或禁用某个IO选项。ACE库内给出的释义如下:

/* Enable asynchronous I/O (ACE_SIGIO), urgent data ACE_SIGURG), non-blocking I/O (ACE_NONBLOCK), or close-on-exec (ACE_CLOEXEC), which is passed as the @a value. */
int enable (int value) const;

2.2.2 ACE_SOCK

  头文件“ace/SOCK.h”

  ACE_SOCK是ACE SOCK wrapper facade的根节点,从ACE_IPC_SAP派生,ACE_SOCK内部调用socket()方法创建了socket对象(ACE_SOCK内部open方法内),如下:

this->set_handle (ACE_OS::socket (protocol_family, type,protocol,protocolinfo,g,flags));

  注意:该方法在连接器ACE_SOCK_Connector的connect()方法和接收器ACE_SOCK_Acceptor的open()方法中被调用。

  除了ACE_IPC_SAP的方法外,ACE_SOCK还提供对socket的管理方法。ACE_IPC_SAP和ACE_SOCK的类关系图如下所示:

  ACE_SOCK对socket的管理方法释义如下:

  与ACE_IPC_SAP类似,ACE_SOCK的构造函数也是protected类型,仅作为抽象类供子类实例化。

  

2.2.3 ACE_SOCK_IO和ACE_SOCK_Stream

  头文件“ace/SOCK_IO.h”和“ace/SOCK_Stream.h”

  ACE_SOCK提供了socket对象,ACE_SOCK_IO和ACE_SOCK_Stream提供socket的数据传输操作,作为一个“仅用作数据传输”的对象存在。ACE_SOCK_IO和ACE_SOCK_Stream的类关系图如下:

  ACE_SOCK_Stream提供的主要输出方法如下:

  其中,recvv_n()和sendv_n()使用结构体iovec,iovec定义如下:

  struct iovec
{
/// byte count to read/write
u_long iov_len;
/// data to be read/written
char *iov_base; // WSABUF is a Winsock2-only type.
# if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != )
operator WSABUF &(void) { return *((WSABUF *) this); }
# endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */
};

  ACE_SOCK_Stream的IO控制超时的方法如下:

2.3 ACE Socket通信机制:ACE_SOCK_Connector和ACE_SOCK_Acceptor

  2.2节提供了ACE Socket的socket对象,本节将给出ACE Socket的通信行为连接器ACE_SOCK_Connector和接收器ACE_SOCK_Acceptor。

2.3.1 ACE_SOCK_Connector

  头文件“ace/SOCK_Connector.h”

  ACE_SOCK_Connector类图如下:

  connect和complete方法说明如下:

  对connect超时的控制如下:

  ACE_SOCK_Connector没有自己的句柄,其connect()方法会接收一个ACE_SOCK_Stream参数,ACE_SOCK_Connector借用这个参数建立主动连接。ACE_SOCK_Connector的实例不存储状态,因此,一个ACE_SOCK_Connector的实例可以在多线程程序中重用,无需加锁。

2.3.2 ACE_SOCK_Acceptor

  头文件“ace/SOCK_Acceptor.h”

  ACE_SOCK_Acceptor的类图如下:

  open和accept方法说明:

  ACE_SOCK_Acceptor总是以正确的顺序调用socket、bind、listen函数。

2.4 本章小结

  本章介绍了ACE Socket 的8个类,但常用的只有地址类ACE_INET_Addr、字节流类ACE_SOCK_Stream、连接器ACE_SOCK_Connector和接收器ACE_SOCK_Acceptor,其余类都是作为基类存在。第3章将针对本章涉及的类和方法,展现ACE客户端和服务端实例代码。

3 举个栗子

  客户端和服务端共享头文件head.h:

#include <iostream>

#include "ace/INET_Addr.h"
#include "ace/SOCK_Stream.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/SOCK_Connector.h"
#include "ace/Time_Value.h" using namespace std; #ifdef _DEBUG
#pragma comment(lib,"ACEd.lib")
#else
#pragma comment(lib,"ACE.lib")
#endif

  客户端代码:

#include "head.h"

int main(int argc, char **argv)
{
ACE_INET_Addr addr(,std::string("127.0.0.1").c_str());
ACE_SOCK_Stream s;
ACE_SOCK_Connector c;
ACE_Time_Value t(,);
if (c.connect(s,addr,&t)==-)
{
int errorCode = ACE_OS::last_error();
cout<<"connector has failed"<<endl;
return ;
}
else
{
char* c1 = "ACE ";
ACE_Time_Value d(,);
if (s.send(c1,,&d) == -)
{
cout<<"send has failed"<<endl;
return ;
}
char buf[BUFSIZ];
ssize_t st = s.recv(buf,BUFSIZ,NULL);
if (st > )
{
buf[st] = ;
cout<<buf<<endl;
::Sleep();
}
else
{
cout<<"recv has failed"<<endl;
return ;
}
}
return ;
}

  服务端代码:

#include "head.h"

int main(int argc, char **argv)
{
ACE_INET_Addr addr(,std::string("127.0.0.1").c_str());
ACE_SOCK_Stream s;
ACE_SOCK_Acceptor a;
ACE_Time_Value t(,);
if (a.open(addr)==-)
{
int errorCode = ACE_OS::last_error();
cout<<"acceptor has failed"<<endl;
return ;
}
else
{
while (true)
{
if (a.accept(s) == -)
{
return ;
}
else
{
ACE_INET_Addr r_addr,l_addr;
s.get_remote_addr(r_addr);
char addr_str[BUFSIZ];
r_addr.addr_to_string(addr_str,BUFSIZ);
cout<<"remote address is "<<addr_str<<endl; s.get_local_addr(l_addr);
l_addr.addr_to_string(addr_str,BUFSIZ);
cout<<"local address is "<<addr_str<<endl; char buf[BUFSIZ];
ssize_t st = s.recv(buf,BUFSIZ,NULL);
if (st > )
{
buf[st]=;
cout<<"receive message : "<<buf<<endl;
} char* cs = "Hello";
if (s.send(cs,,&t) == -)
{
cout<<"send has failed"<<endl;
return ;
}
}
}
}
return ;
}

  客户端只输出了Hello,比较简单,就不截图展示了。服务端截图如下:

参考书:C++ Network Program v1,Mastering complexity with ACE and Patterns。

ACE Socket Wrapper Facade的更多相关文章

  1. 每周一荐:学习ACE一定要看的书

    作 者:david++发布时间:2012/06/08 09:02文章地址:http://game-lab.org/?p=320 近两个月都在学习ACE,一个超级强大,也超级复杂的网络框架库.对ACE的 ...

  2. ACE工具概述

    一:ACE简介 ADAPTIVE 通信环境(ACE,ADAPTIVE Communication Enviroment)是一种广泛的主机基础设施中间件,ACE可以免费获得,可以在http://ace. ...

  3. Linux下经常使用的C/C++开源Socket库

    1.      Linux Socket Programming In C++ : http://tldp.org/LDP/LG/issue74/tougher.html 2.      ACE: h ...

  4. Linux下经常使用的C/C++开源Socket库【转】

    转自:https://www.cnblogs.com/gccbuaa/p/7015599.html 1.      Linux Socket Programming In C++ : http://t ...

  5. ACE服务端编程2:ACE跨平台之数据类型和宽字符

    ACE网络库的主要优势之一就是跨平台,ACE提供了操作系统API和编译器级别的跨平台解决方法,使开发人员不用再去关心操作系统和编译器的差异,但因此也带来了ACE的复杂性. ACE网络库的组织结构主要分 ...

  6. Socket聊天程序——服务端

    写在前面: 昨天在博客记录自己抽空写的一个Socket聊天程序的初始设计,那是这个程序的整体设计,为了完整性,今天把服务端的设计细化记录一下,首页贴出Socket聊天程序的服务端大体设计图,如下图: ...

  7. tomcat源码分析(三)一次http请求的旅行-从Socket说起

    p { margin-bottom: 0.25cm; line-height: 120% } tomcat源码分析(三)一次http请求的旅行 在http请求旅行之前,我们先来准备下我们所需要的工具. ...

  8. c++程序员必知的几个库

    c++程序员必知的几个库 1.C++各大有名库的介绍——C++标准库 2.C++各大有名库的介绍——准标准库Boost 3.C++各大有名库的介绍——GUI 4.C++各大有名库的介绍——网络通信 5 ...

  9. c++资源之不完全导引 (转)

    c++资源之不完全导引 (转) 转:http://www.cnblogs.com/suiyingjie/archive/2008/02/24/1079411.html 本文2004年5月首发于< ...

随机推荐

  1. Python学习入门基础教程(learning Python)--6.4 Python的list与函数

    list是python下的一种数据类型,他和其他类型如整形.浮点型.字符串等数据类型一样也可作为函数的型参和实参来使用! 1.list作为参数 list数据类型可以作为函数的参数传递给函数取做相应的处 ...

  2. Linux:用at和crontab调度作业

    一.有2种作业调度方式 1.突发性的,就是只运行作业一次而不是定期运行,使用at命令. 例如在进程A运行一段时间后关闭该进程. 2.定期运行,就是每隔一定的周期运行一次,使用crontab命令. 如每 ...

  3. Android插件简介

    /** * @actor Steffen.D * @time 2015.02.06 * @blog http://www.cnblogs.com/steffen */ Android插件简介 Andr ...

  4. 使用div模拟textarea,实现文本输入框高度自适应(附:js控制textarea实现文本输入框高度自适应)

    一.使用textarea标签进行多行文本的输入有很多限制,比如不能实现高度自适应,会出现难看的滚动条等问题. HTML5中添加了一个新属性contenteditable,该属性可以让input,tex ...

  5. ACM第二题 生理周期

    人生来就有三个生理周期,分别为体力.感情和智力周期,它们的周期长度为23天.28天和33天.每一个周期中有一天是高峰.在高峰这天,人会在相应的方面表现出色.例如,智力周期的高峰,人会思维敏捷,精力容易 ...

  6. openssh-clients(CentOS 7 自带的SSH客户端)

    OpenSSH 有自带的服务端 openssh-server(sshd服务) 和 客户端 openssh-clients(ssh命令),平时使用SSH远程登陆Linux都是在本地Windows上使用P ...

  7. Shell终端收听音乐--网易云音乐命令行版

    Musicbox:网易云音乐命令行版本 高品质网易云音乐命令行版本,简洁优雅,丝般顺滑,基于Python编写. 这款命令行的客户端使用 Python 构建,以 mpg123 作为播放后端: Vim 式 ...

  8. Front-End(五)——工具使用

    mac端推荐使用sublime+emmet. 环境搭建 sublime 官网下载sublime text 02或者03,03现在(2016.07)还是测试版,我使用的是text02. emmet su ...

  9. BZOJ 1303 【CQOI2009】中位数图

    baidu了一下bzoj水题列表...找到这道题.   题目大意:给定一个数t,在给定的一段包含1-n的序列中找出多少个长度为奇数子序列的中位数为t. 第一眼没看数据范围,于是开心的打了一个O(n^3 ...

  10. 在http编程的门口----飞牛网自动下单,查单

    刚进这个公司,以前没接触过http编程,所以这两天做了个小例子来熟悉http编程,有点晕..... 不过还是做出来了,虽然有点粗糙,总结一下这个小软件: 主要使用QNetworkAccessManag ...