ACE_Message_Block介绍
前言之Block的长度
ACE_Message_Block的内存管理:
1 依赖其他的buffer
ACE_Message_Block* mb = new ACE_Message_Block(data,length);
注意:
1 这种方式下创建一个block,引用了参数data的内存空间;block被释放的时候也不会释放data的内存;
2 data的内存由data的创建者自己管理;
3 如果改变了data中的内容就会改变block的内容;
4 这种情况下,除了使用者自行释放new出来的ACE_Message_Black之外,还要管理buffer的生命周期,所以这种情景适合buffer的生命周期比较长,或者固定的情况。
例1:
#include "ace/Message_Block.h"
#include <iostream>
using namespace std;
int main(int, char *[])
{
const int length = 100;
char* data = new char[length];
ACE_Message_Block* mb = new ACE_Message_Block(data,length);
ACE_Message_Block* mb1=mb;
mb1->copy("Hello World!");
data[0]='F';
cout<<data<<endl;
mb1->release();//或者使用 delete mb1;
delete[] data;
};
输出:
Fello World
2 自己管理
ACE_Message_Block* mblk = new ACE_Message_Block(BUFFERSIZE);
注意:与(1)中要自行管理buffer的声明周期不同的是,动态开辟内存由ACE_Message_Block自行管理,只需要最后的使用者调用release方法即可释放所有开辟出来的动态内存,这种方式比较常见。通常会将消息放入消息队列中,并后来再取出使用(使用完由最后的使用者释放内存)。
例2:
#include "ace/Message_Block.h"
#include <iostream>
using namespace std;
int main(int, char *[])
{
const int length = 100;
ACE_Message_Block* mb = new ACE_Message_Block(length);
ACE_Message_Block* mb1 = mb;
mb1->copy("Hello World!");
cout<<mb1->rd_ptr()<<endl;
mb1->release();//或者使用 delete mb1;
};
输出:
Hello World!
写入
写入:wr_ptr()
ACE_OS::sprintf(mblk->wr_ptr(),"%s",str.c_str());
mblk->wr_ptr(str.size());
写入:copy(buffer,length) 和 copy(c_str())
int copy(const char *buf, size_t n);拷贝n个字节,此方法适合拷贝buffer里的内容,length方法告诉拷贝多少个字符
例4:mb->copy(c_str())
#include "ace/Message_Block.h"
#include <iostream>
using namespace std;
int main(int, char *[])
{
char data[100];
ACE_Message_Block* mb = new ACE_Message_Block(data,sizeof(data));
mb->copy("Hello ");
mb->copy("World!");
cout<<data<<endl;
};
程序输出:
Hello
例5:int copy(const char *buf, size_t n);
将0-99放入到消息体中,最后又加了一个99,是为了添加'\0',方便输出。
#include "ace\Message_Block.h"
#include "boost\lexical_cast.hpp"
using namespace boost;
#include "ace\OS.h"
int main(int argc ,char * argv[])
{
//test_scp();
ACE_Message_Block* mb = new ACE_Message_Block(1024);
string s;
for (int i=0;i<100;i++)
{
s = lexical_cast<string>(i);
mb->copy(s.c_str(),s.size());
}
mb->copy(s.c_str());
ACE_OS::printf("%s",mb->rd_ptr());
return 0;
};
输出:
012345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989
999请按任意键继续. . .
读取数据:rd_ptr() 和 length()
下面的操作开辟一个新的消息,大小能盛放100个字符,往消息里面追加一个字符串,最后把这个字符串发送到远端(字符串的起始位置mb->rd_ptr(),字符串的长度mb->length()),将会把 ‘c’、'a'、'r'、'e'、'a'这五个字符发送到对方那里
ACE_Message_Block* mb = new ACE_Message_Block(100);
mb->copy("carea");
int length = udp_sender.send_udp(mb->rd_ptr(),mb->length(),remote_addr);
测试输出如下:
UDP(1032)
UDPReceiver(1032)
UDPReceiver receive length[5],receive_udp:[0x63 0x61 0x72 0x65 0x61
OK,send successed
received:carea
ACE_Message_Block常用接口一览
ACE_Message_Block中有多个获取大小或者长度的函数,容易混淆.
下图是根据ACE_Message_Block(实际是ACE_Data_Block)空间的处理状况所绘,能比较清晰的反应出它们的异同.
需要注意,为了表现出多样性,下图是wr_ptr(),rd_ptr(),size()都调用过之后的情景.
红色表示是ACE_Message_Block独有的函数, 其余则ACE_Message_Block和ACE_Data_Block均有.
矩形纸上函数的返回值均为指针类型,之下的返回值均为size_t类型.
函数 | 说明 |
length() | 有效数据的长度 == wr_ptr() – rd_ptr() |
size() | 全部可用空间的长度,如果没有size()而变小,则等同capacity() == mark() – base() |
space() | 剩余可用空间的长度 <= size() - length(),因为不含rd_ptr()移动过的空间 == mark() – wr_ptr() |
capacity() | 最大空间的长度(ACE_Message_Block构造或初始化时所用参数值) == end() – base() |
total_length() | 复合消息(ACE_Message_Block内单向链 cont())的总长度 |
total_size() | 复合消息(ACE_Message_Block内单向链 cont())的总大小 |
total_capacity() | 复合消息(ACE_Message_Block内单向链 cont())的总空间大小 |
ACE_Message_Block常用接口
length()返回已经使用的字节数
seize(size_t new_size)动态申请更多内存
#include "ace/Message_Block.h"
#include "ace/OS.h"
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char * argv[])
{
const int BUFFERSIZE = 10;
ACE_Message_Block* mblk = new ACE_Message_Block(BUFFERSIZE);
cout<<"mblk size "<<mblk->size()<<endl;
string str("Hello ACE_Message_Block");
//check the space wheather enough befor write to mblk
if (mblk->space()<str.size())
{
mblk->size(mblk->size()+str.size());
}
cout<<"mblk size "<<mblk->size()<<endl;
ACE_OS::sprintf(mblk->wr_ptr(),"%s",str.c_str());
mblk->wr_ptr(str.size());
//check the space wheather enough befor write to mblk
if (mblk->space()<str.size())
{
mblk->size(mblk->size()+str.size());
}
cout<<"mblk size "<<mblk->size()<<endl;
ACE_OS::sprintf(mblk->wr_ptr(),"%s",str.c_str());
mblk->wr_ptr(str.size());
ACE_OS::printf("message :%s",mblk->rd_ptr());
mblk->release();
return 0;
};
输出如下:
以上两个方法都会自动移动 wr_ptr()指针
mb->copy(s.c_str());
ACE_OS::sprintf(mblk->wr_ptr(),"%s",str.c_str());
mblk->wr_ptr(str.size());
注:本文使用标题3,标题4排版