ACE Socket wrapper façade提供的好处有:
① 提高了类型安全。对于该优点我的理解是:在不用ACE的情况下对SOCKET进行操作时,建立连接和收发两种功能都在同一个SOCKET下执行,那样我们很可能在没有建立连接的情况下就调用收发的方法,而此时的编译器并不能检测到这种错误。而用了ACE之后,我们将建立连接和收发两种功能分别封装在两个类中,我们无法在连接类中调用收发的行为,这样就避免了这种情况的发生。
② 保证可移植性。这个特点是不言而喻的,ACE的设计目的就是这样。
③ 简化了常见的使用情况。这也是ACE设计的一个目的。
ACE中将C Socket API中的函数划分为三种角色:
① 主动连接者角色:对等应用程序中的一方扮演,用来发起一个对远程对等方的连接。
② 被动连接者角色:对等应用程序中的一方扮演,用来接收一个来自远程对等方的连接。
③ 通信角色:由对等应用程序中的双方共同扮演,由于在建立连接后交换数据。
ACE中的地址类
ACE_Addr类位于ACE网络地址继承结构的根部。其中ACE_Addr类中定义了大量的方法。它还定义了一个静态的数据成员sap_any。ACE_INET_Addr继承自ACE_Addr类,他表示internet的地址连接。使用ACE_INET_Addr类的好处主要有两点:
① 它能够确保sockaddr_in中的所有字节都被初始化为零
② 它自动将端口号和IP地址转换为网络字节序。
ACE_IPC_SAP类
由于句柄会造成可移植方面的问题(比如在Linux和windows下的句柄概念就不同),所以ACE通过两种方式解决了这种不可移植问题:
① 提供了跨平台的ACE_HANDLE类型定义
② 定义了ACE_INVALID_HANDLE宏标志无效句柄(比如windows下为一个INVALID_HANDLE,UNIX为-1)。
解决移植问题还远远不够,我们还要实现面向对象,这样就出现了ACE_IPC_SAP类,该类提供了基本的I/O操作能力。当具体到网络编程方面时,产生了一个继承自ACE_IPC_SAP类的子类,ACE Socket wrapper façade的根类------ACE_SOCK。它也是一个抽象类,它为子类提供了创建/销毁socket句柄、获得对等端的网络地址和设置读取socket选项的方法。(ACE_SOCK类并没有在析构中关闭句柄,而是提供了一个close方法,我还不清楚)
ACE_SOCK_Connector类
Socket API在面向连接的协议中扮演了三种角色,但只有两种socket模式。
① 数据模式
② 被动模式
这样就没有一种socket模式来支持主动连接的角色。为了解决这个问题,特地定义了ACE_SOCK_Connnect类。由于Socket API不需要一个工厂socket来连接一个“数据模式”socket,所以ACE_SOCK_Connect类并不继承自ACE_SOCK。我对这点的理解是,在采用Socket API编程时,在客户端,也就是ACE_SOCK_Connector类发生作用的一端,并不需要一个socket句柄来标识,而服务器端必须有一个socket来标识。也就是说,客户端只需要一个面向连接的socket,而在服务器端则需要两个socket,一个面向连接,一个为服务器的socket。因此ACE_SOCK_Connector类不需要保留socket而ACE_SOCK_Acceptor需要保留一个socket。
ACE_SOCK_Stream类
ACE_SOCK_Stream类定义了一个数据模式下的只传输功能的对象。它继承自ACE_SOCK_IO类,在ACE_SOCK_Acceptor和ACE_SOCK_Connector工厂中初始化。
ACE_SOCK_Acceptor类
继承自ACE_SOCK类,又来被动的建立一个新的通信断点。
以下为我自己编写的联系代码
服务器端代码
int _tmain(int argc, _TCHAR* argv[])
{
const char *pathname = "index.html";
const char *server_hostname = "127.0.0.1";
ACE_INET_Addr server_addr;
ACE_SOCK_Acceptor acceptor;
ACE_SOCK_Stream peer;
if(server_addr.set(80)==-1)
return 1;
if(acceptor.open(server_addr)==-1)
return 1;
for (;;)
{
char buf[BUFSIZ];
if(acceptor.accept(peer) == -1)
return 1;
std::cout<<"connect"<<std::endl;
SSIZE_T n=peer.recv(buf,sizeof buf);
ACE::write_n(ACE_STDOUT,buf,n);
ACE::write_n(ACE_STDOUT,buf,n);
if(peer.send_n(buf,n) == -1)
return 1;
peer.close();
}
return 0;
}
客户端代码
int _tmain(int argc, _TCHAR* argv[])
{
const char *pathname = argc > 1?argv[1]:"index.html";
const char *server_hostname = argc>2?argv[2]:"127.0.0.1";
ACE_SOCK_Connector connector;
ACE_SOCK_Stream peer;
ACE_INET_Addr peer_addr;
if(peer_addr.set(80,server_hostname)==-1)
{
std::cout<<"设置失败"<<std::endl;
return 1;
}
else if(connector.connect(peer,peer_addr)==-1)
{
std::cout<<"连接失败"<<std::endl;
system("pause");
return 1;
}
char buf[BUFSIZ];
iovec iov[3];
iov[0].iov_base = "GET ";
iov[0].iov_len = 4;
iov[1].iov_base = (char*)pathname;
iov[1].iov_len = strlen(pathname);
iov[2].iov_base = "HTTP/1.0\r\n\r\n";
iov[2].iov_len = 13;
if(peer.sendv_n(iov,3) == -1)
return 1;
for(SSIZE_T n;(n=peer.recv(buf,sizeof buf))>0;)
{
ACE::write_n(ACE_STDOUT,buf,n);
}
system("pause");
return 0;
}