转载 用ACE开发网络通信程序

本文介绍如何使用ACE库进行网络通信编程,包括连接服务器、发送序列化数据及接收解析数据等关键步骤。通过示例代码展示了ACE的角色分工及其在网络通信中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载 用ACE开发网络通信程序 时间: 2008.12.25 13:49:00 标签: 该程序将演示如何将一个简单结构序列化后发送到网络上,如何从网络上接收到数据后反序列化回结构。 ACE的C++ WRAPPER FACADE层将网络通信分成三种角色:连接者(ACE_SOCK_Connector)、等待者(ACE_SOCK_Acceptor)和传输者(ACE_SOCK_Stream)。 建立连接 首先使用ACE_SOCK_Connector::connect连接某个服务器(使用ip地址和端口号),该服务器上使用ACE_SOCK_Acceptor::accept等待外部的连接请求。 ACE_INET_Addr类进行管理SOCKET通信使用的IP地址和端口号。 当连接建立的时候,连接者和等待者都初始化一个传输者用于通信。 下面就是连接者如何连接本机的7777端口的服务程序代码: #include using namespace std; #include "ace/INET_Addr.h" #include "ace/SOCK_Stream.h" #include "ace/SOCK_Connector.h" int main(void) { ACE_INET_Addr address("127.0.0.1:7777"); ACE_SOCK_Connector connector; ACE_SOCK_Stream stream; if(connector.connect(stream,address)==-1) { cout< using namespace std; #include "ace/INET_Addr.h" #include "ace/SOCK_Stream.h" #include "ace/SOCK_Acceptor.h" int main(void) { ACE_SOCK_Acceptor acceptor; //本地端口7777的ACE_INET_Addr对象 ACE_INET_Addr address; address.set(7777); //绑定本地端口,并且设置为监听状态 if(acceptor.open(address)==-1) { cout< using namespace std; #include "ace/INET_Addr.h" #include "ace/SOCK_Stream.h" #include "ace/SOCK_Connector.h" #include "ace/CDR_Stream.h" class SHMRecord { public: SHMRecord():pData_(NULL){} ACE_UINT16 type_; ACE_UINT32 offset_; void* pData_; ACE_UINT32 dataLength_; size_t size() const { return 2+4+4+dataLength_; } ~SHMRecord() { if(pData_!=NULL) delete[] static_cast(pData_); } }; int operator<<(ACE_OutputCDR & cdr,SHMRecord const& record) { cdr<(record.pData_),record.dataLength_); return cdr.good_bit(); } int operator>>(ACE_InputCDR & cdr,SHMRecord & record) { cdr>>record.type_; cdr>>record.offset_; cdr>>record.dataLength_; record.pData_=new char[record.dataLength_](); cdr.read_char_array(static_cast(record.pData_),record.dataLength_); return cdr.good_bit(); } int main(void) { ACE_INET_Addr address("127.0.0.1:7777"); ACE_SOCK_Connector connector; ACE_SOCK_Stream stream; if(connector.connect(stream,address)==-1) { cout<(record.pData_),"hih"); const size_t size=record.size()+ACE_CDR::MAX_ALIGNMENT; ACE_OutputCDR payload(size); payload<rd_ptr(); iov[0].iov_len=8; iov[1].iov_base=payload.begin()->rd_ptr(); iov[1].iov_len=size; stream.sendv_n(iov,2); cout<(record.pData_)<>操作,就像上面的例子一样。 这种方式和支持标准C++流的方式是一样的。那么,为什么不直接使用标准C++流呢?因为ACE所支持的平台很多,有些编译器不支持标准C++流。并且据我个人的体验,标准C++流在内存管理上是封装的,你不可能通过公有方法获得内部关里的缓冲区的指针,除非自己定义自己的派生类,这并不容易。还有一个原因是不同编译器和不同的硬件使用了不同的字节对齐方式(大尾数法和小尾数法)。使用ACE的cdr类就可以保证各种环境下都能使用,因为它在内部使用了CORBA公共数据表示的格式。 对于基本的数值类型,各个平台也有可能有长度的差异,比如int究竟是16,32还是64。所以这里使用了ACE提供的基本数值类型,比如ACE_UINT32。 在这个示例程序里,我们实际上创建了两个ACE_OutputCDR对象,一个用来表示数据头,一个存发实际结构中的数据。数据头中前4个字节存放了一个布尔值,表示本机的字节顺序,后面四个字节表示第二个对象的实际长度。 因此,接收数据时首先接收固定长度的头对象,取得字节顺序标志后,调整字节顺序,然后获取实际长度,根据该长度接收第二个ACE_OutputCDR对象存放的实际数据。 下面的例子演示了如何接收发送来的数据。 int main(void) { ACE_SOCK_Acceptor acceptor; ACE_INET_Addr address; address.set(7777); if(acceptor.open(address)==-1) { cout< spBlock(new ACE_Message_Block(ACE_DEFAULT_CDR_BUFSIZE)); ACE_CDR::mb_align(spBlock.get()); if(stream.recv_n(spBlock->wr_ptr(),8)==8)//receive the header of CDR { //parse the cdr header spBlock->wr_ptr(8); ACE_InputCDR cdr(spBlock.get()); ACE_CDR::Boolean byte_order; cdr>>ACE_InputCDR::to_boolean(byte_order); cdr.reset_byte_order(byte_order); ACE_CDR::ULong length; cdr>>length; //receive the data from master spBlock->size(length+8+ACE_CDR::MAX_ALIGNMENT); if(stream.recv_n(spBlock->wr_ptr(),length)==length) { spBlock->wr_ptr(length); //必须重新创建一个CDR对象,否则解析不正确 ACE_InputCDR cdr2(spBlock.get()); ACE_CDR::Boolean byte_order; cdr2>>ACE_InputCDR::to_boolean(byte_order); cdr2.reset_byte_order(byte_order); ACE_CDR::ULong length; cdr2>>length; auto_ptr spRecord(new SHMRecord); cdr2>>*spRecord; cout<type_<offset_<(spRecord->pData_)<dataLength_<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值