RakNet--Receiving Packets
![]() |
当一个数据包到来时,例如Receive返回一个非零,处理这个数据包需要三步: 1. 确定数据包类型。使用如下的代码可以返回这个类型值。 unsigned char GetPacketIdentifier(Packet *p) { if ((unsigned char)p->data[0] == ID_TIMESTAMP) return (unsigned char) p->data[sizeof(unsigned char) + sizeof(unsigned long)]; else return (unsigned char) p->data[0]; }
2. 处理数据 接收结构 如果你原始发送一个结构体,可以按照如下的方式转化出这个结构体: if (GetPacketIdentifier(packet)==/* 在这里使用赋值的数据包标识符 */) DoMyPacketHandler(packet); // 可以将这个函数放到任何位置,在处理游戏的状态类中比较好 void DoMyPacketHandler(Packet *packet) { // 将数据转化为适合类型的结构体 MyStruct *s = (MyStruct *) packet->data; assert(p->length == sizeof(MyStruct)); // 如果传输的是结构体这块这样处理比较好 if (p->length != sizeof(MyStruct)) return; // 在这里调用函数处理结构体 MyStruct *s }
使用注释: 1. 将数据包的数据转换为适合类型结构体的指针,这样可以避免复制数据造成的开销。然后在这种情况下,如果你修改了结构体中的任何数据,数据包中的数据也会被修改掉。当然了,这种情况不是我们想要看到的。作为一个服务器,在中继数据的时候要多加注意,因为中继数据会引起未知的Bugs。 2. 尽管assert不是特别必要,但是如果我们对标识符赋值错误了,assert对于发现bug非常有用。 3.在有人要发送一个大小或类型无效的数据包,使得服务器或客户端崩溃情况时,if语句就显得非常有用。在实践中,没有发生过这样的事情,虽然没有出现过也不能说明是安全的。
接收一个位流数据(BitStream) 如果你最初发送的是一个Bitstream,那就需要创建一个BitStream,按照我们的写入顺序来解析数据。使用数据和数据包的长度来创建一个BitStream。我们写入数据的时候,使用的是Write函数,那么就使用Read函数读取数据。如果前面使用的WriteCompressed函数,那读取数据就要使用ReadCompressed函数。如果我们条件性的写入任何数据,依据这个逻辑分支。在接下来的例子中给出了处理在Creating packets中的地雷的数据: void DoMyPacketHandler(Packet *packet) { Bitstream myBitStream(packet->data, packet->length, false); // false指定不拷贝数据,提高效率 myBitStream.Read(useTimeStamp); myBitStream.Read(timeStamp); myBitStream.Read(typeId); bool isAtZero; myBitStream.Read(isAtZero); if (isAtZero==false) { x=0.0f; y=0.0f; z=0.0f; } else { myBitStream.Read(x); myBitStream.Read(y); myBitStream.Read(z); } myBitStream.Read(networkID); // 在结构体中这里是 NetworkID networkId myBitStream.Read(systemAddress); // 在结构体中这里是SystemAddress systemAddress }
3. 通过将数据包传递给RakPeerInterface实例的DeallocatePakcet(Packet *packet)释放数据包。 |
![]() |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步