socket
、TLI、STREAM管道和FIFO为访问局部和全局IPC机制提供广泛的接口。但是,有许多问题与这些不统一的接口有关联。比如类型安全的缺乏和多维度的复杂性会导致成问题的和易错的编程。的IPC SAP类属提供了统一的层次类属,对那些麻烦而易错的接口进行封装。在保持高性能的同时,IPC SAP被设计用于改善通信软件的正确性、易学性、可移植性和可复用性。类属

图
2-1 IPC SAP类属
根据底层使用的不同
IPC接口,IPC SAP类被划分为四种主要的类属,图2-1描述了这一划分。ACE_IPC_SAP类提供的一些函数是所有IPC接口公有的。有四个不同的类由此类派生而出,每个类各自代表ACE包含的一种IPC SAP包装类属。这些类封装适用于特定IPC接口的功能。例如,ACE_SOCK类包含的功能适用于BSD socket编程接口,而ACE_TLI包装TLI编程接口。在这四个类的每一个类下面都有一整层次的包装类,它们完整地包装底层接口,并提供高度可复用、模块化、安全和易用的包装类。
类属(ACE_SOCK)该类属中的类都位于
ACE_SOCK之下;它提供使用BSD socket编程接口的Internet域和UNIX域协议族的接口。这个类属中的类被进一步划分为:
- Dgram
表
2-1详细描述了该类属中的类以及它们的职责:
类名 | 职责 |
ACE_SOCK_Acceptor | 用于被动的连接建立,基于 BSD accept()和listen()调用。 |
ACE_SOCK_Connector | 用于主动的连接建立,基于 BSD connect()调用。 |
ACE_SOCK_Dgram | 用于提供基于 UDP(用户数据报协议)的无连接消息传递服务。封装了sendto()和receivefrom()等调用,并提供了简单的send()和recv()接口。 |
ACE_SOCK_IO | 用于提供面向连接的消息传递服务。封装了 send()、recv()和write()等调用。该类是ACE_SOCK_Stream和ACE_SOCK_CODgram类的基类。 |
ACE_SOCK_Stream | 用于提供基于 TCP(传输控制协议)的面向连接的消息传递服务。派生自ACE_SOCK_IO,并提供了更多的包装方法。 |
ACE_SOCK_CODgram | 用于提供有连接数据报( connected datagram)抽象。派生自ACE_SOCK_IO;它包含的open()方法使用bind()来绑定到指定的本地地址,并使用UDP连接到远地地址。 |
ACE_SOCK_Dgram_Mcast | 用于提供基于数据报的多点传送 (multicast)抽象。包括预订多点传送组,以及发送和接收消息的方法 |
ACE_SOCK_Dgram_Bcast | 用于提供基于数据报的广播 (broadcast)抽象。包括在子网中向所有接口广播数据报消息的方法 |
表
2-1 ACE_SOCK中的类及其职责
在下面的部分,我们将要演示怎样将
IPC_SAP包装类直接用于处理进程间通信。记住这些只是ACE的冰山一角。在教程的后续章节中将会介绍其他类和组件。2.2.1使用ACE的流ACE
中的流包装提供面向连接的通信。流数据传输包装类包括ACE_SOCK_Stream和ACE_LSOCK_Stream,它们分别包装TCP/IP和UNIX域socket协议数据传输功能。连接建立类包括针对TCP/IP的ACE_SOCK_Connector和ACE_SOCK_Acceptor,以及针对UNIX域socket的ACE_LSOCK_Connector和ACE_LSOCK_Acceptor。Acceptor
类用于被动地接受连接(使用BSD accept()调用),而Connector类用于主动地建立连接(使用BSD connect()调用)。下面的例子演示接收器和连接器是怎样用于建立连接的。该连接随后将用于使用流数据传输类来传输数据。
例
2-1#include "ace/SOCK_Acceptor.h"
#include "ace/SOCK_Stream.h"
#define SIZE_DATA 18
#define SIZE_BUF 1024
#define NO_ITERATIONS 5
class
Server{
public:
Server
(int port): server_addr_(port),peer_acceptor_(server_addr_){
data_buf_= new char[SIZE_BUF];
}
//Handle the connection once it has been established. Here the
//connection is handled by reading SIZE_DATA amount of data from the
//remote and then closing the connection stream down.
int
handle_connection(){
// Read data from client
for(int i=0;i
{
int byte_count=0;
if( (byte_count=new_stream_.recv_n (data_buf_, SIZE_DATA, 0))==-1)
ACE_ERROR ((LM_ERROR, "%p\n", "Error in recv"));
else
{
data_buf_[byte_count]=0;
ACE_DEBUG((LM_DEBUG,"Server received %s \n",data_buf_));
}
}
// Close new endpoint
if (new_stream_.close () == -1)
ACE_ERROR ((LM_ERROR, "%p\n", "close"));
return 0;
}
//Use the acceptor component peer_acceptor_ to accept the connection
//into the underlying stream new_stream_. After the connection has been
//established call the handle_connection() method.
int
accept_connections(){
if (peer_acceptor_.get_local_addr (server_addr_) == -1)
ACE_ERROR_RETURN ((LM_ERROR,"%p\n","Error in get_local_addr"),1);
ACE_DEBUG ((LM_DEBUG,"Starting server at port %d\n",
server_addr_.get_port_number ()));
// Performs the iterative server activities.
while(1)
{
ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
if (peer_acceptor_.accept (new_stream_, &client_addr_, &timeout)== -1)
{
ACE_ERROR ((LM_ERROR, "%p\n", "accept"));
continue;
}
else
{
ACE_DEBUG((LM_DEBUG,
"Connection established with remote %s:%d\n",
client_addr_.get_host_name(),client_addr_.get_port_number()));
//Handle the connection
handle_connection();
}
}
}
private:
char *data_buf_;
ACE_INET_Addr server_addr_;
ACE_INET_Addr client_addr_;
ACE_SOCK_Acceptor peer_acceptor_;
ACE_SOCK_Stream new_stream_;
};
int
main(int argc, char *argv[]){
if(argc<2)
{
ACE_ERROR((LM_ERROR,"Usage %s
", argv[0])); ACE_OS::exit(1);
}
Server server(ACE_OS::atoi(argv[1]));
server.accept_connections();
}
上面的例子创建了一个被动服务器,侦听到来的客户连接。在连接建立后,服务器接收来自客户的数据,然后关闭连接。
Server类表示该服务器。
