注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

BCB-DG's Blog

...

 
 
 

日志

 
 

Raknet(6)——Bitstream  

2015-02-13 12:27:12|  分类: Socket |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
//转

Bitstream概述

Bitstream类是一个RakNet命名空间下的helper类,是一个用于打包、解包bits的动态数组。它有如下四个优点:

1.动态的创建数据包

2.压缩

3.写入Bits

4.字节序转化

对 于结构体打包来说,需要预定义结构体,并将他们转化为一个(char*)的类型。使用Bitstream,你可以在运行时根据上下文选择写入数据块。 Bitstreams可以使用SerializeBitsFromIntegerRange()和SerializeFloat16()函数压缩原有的数 据类型。

当然了,你还可以写入Bits。大多数时间下你不需要关心这些事情。然而,当写入布尔值时它会自动仅仅写入一个Bit位。这种方式在加密中非常有效,因为你的数据不再是按照字节对齐。(译者注:使得破解者无法获取你的数据结构)

 

写入数据

Bitstream 是一个可以带任何数据类型的模板类。如果是一个内建的数据类型(译者注:指的是非自定义的数据类型),例如NetworkIDObject,它使用了局部 模板特化来更有效的写入数据类型。如果它是一个原生类型或者一个结构体,他写入一个单独的bits,与memcpy()有些类似。你可以传递包含多个数据 成员的结构体给bitstreams。然后,你需要序列化每一个单独的元素以纠正字节序。(例如:在PC和Mac之间通讯需要如此)

struct MyVector
{
	float x,y,z;
} myVector;

// 没有字节序交换
bitStream.Write(myVector);

// 有字节序交换
#undef __BITSTREAM_NATIVE_END
bitStream.Write(myVector.x);
bitStream.Write(myVector.y);
bitStream.Write(myVector.z);

// 你可以重载左移右移操作符
// 右移操作符必须在RakNet命名空间里,或者使用BitStream.h中的命名空间代替。
// 使用std::string会引起一些错误
namespace RakNet
{
	RakNet::BitStream& operator << (RakNet::BitStream& out, MyVector& in)
	{
		out.WriteNormVector(in.x,in.y,in.z);
		return out;
	}
	RakNet::BitStream& operator >> (RakNet::BitStream& in, MyVector& out)
	{
		bool success = in.ReadNormVector(out.x,out.y,out.z);
		assert(success);
		return in;
	}
} // RakNet命名空间

// 从BitStream中读取
myVector << bitStream;
// 写入BitStream
myVector >> bitStream;

可选的 —— 其中的一个构造函数是以字节长度为参数。如果你清楚传递的数据长度,你可以传递这个数给Bitstream的构造函数,可以避免创建bitstream时内部动态重新分配内存。

参见Creating Packets获得更多的细节。

读取数据

读取数据相对简单。创建一个bitstream,在构造函数中指定你的数据。

// 假设我们已经有了一个 Packet *对象
BitStream myBitStream(packet->data, packet->length, false);
struct MyVector
{
	float x,y,z;
} myVector;

// 没有字节序交换的
bitStream.Read(myVector);

// 有字节序交换的 (RakNetDefines.h中的__BITSTREAM_NATIVE_END宏必须被注释掉)
#undef __BITSTREAM_NATIVE_END
#include "BitStream.h"
bitStream.Read(myVector.x);
bitStream.Read(myVector.y);
bitStream.Read(myVector.z);

参见 Receiving Packets 获得完整的例子。

序列化数据

你可以通过使用BitStream::Serialize()替代Read()或者Write(),这样就可以使用相同的读写函数了。

struct MyVector
{
	float x,y,z;
	// writeToBitstream==true 表示写数据 writeToBitstream==false 表示读数据
	void Serialize(bool writeToBitstream, BitStream *bs)
	{
		bs->Serialize(writeToBitstream, x);
		bs->Serialize(writeToBitstream, y);
		bs->Serialize(writeToBitstream, z);
	}
} myVector;

参见 Receiving Packets 获得完整的例子。

有用的函数

参见BitSteam.h可以获得完整的函数列表

Reset 函数

重置字节流,清空所有数据

Write 函数

写入函数在字节流的结尾将数据写入。你应该使用类似的Read函数从bitstream中读取数据

Read 函数

读取函数按照从头到尾的顺序读取bitstream中已经存在的数据。如果bitstream中没有任何数据,Read函数返回false。

WriteBitsFromIntegerRange, ReadBitsFromIntegerRange,SerializeBitsFromIntegerRange 函数

如果一个数字知识使用的特殊的值区间(例如 10-20),当比特数写入那个值区间内,这个函数将会自动。

WriteCasted, ReadCasted 函数

写一个类型的变量,当他需要被转化为其他数据类型。例如:WriteCasted< char >( 5 )等同于 char c = 5; Write( c );

WriteNormVector, ReadNormVector 函数

写入一个常规的向量,其中每一个元素的范围都是-1 — 1。每一个元素有16位。

WriteFloat16, ReadFloat16 函数

给出浮点数的最大最小值,以65535划分区间,将结果写入到一个16字节里(精度有损)。

WriteNormQuat, ReadNormQuat 函数

写入一个四元数到16 * 3 + 4位数据中(精度有损)。

WriteOrthMatrix, ReadOrthMatrix 函数

转化一个正交矩阵为四元数,然后调用WriteOrthMatrix/ReadOrthMatrix函数

GetNumberOfBitsUsed, GetNumberOfBytesUsed

给出已写入的字节或者位的大小。

GetData 函数

给出bitstream内部数据的指针。他是一个由malloc分配的(char*)指针,在你需要直接访问bitstream的数据时使用。

  评论这张
 
阅读(1720)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017