在章节6 我们实现了利用protbuffer进行数据传送。在实际传送过程中,我们往往还需要对数据添加一些额外的信息,以便接收方能正确处理该数据包。
对此,可采用一些符合自定义要求的结构。这里就以如下结构作为代表:
其中msgId代表该协议对应的消息Id, bodyLength表明body占用长度, serialNo对应请求序列号,sessionId,对应回话Id, from 表明来原, body表明真正携带的数据
注意:该结构只针对服务器之间的通信,对于服务器与客户端之间的通信需要在重新设计。
新增包结构类:PacketHead.h
#ifndef __PACKET_HEAD_H__
#define __PACKET_HEAD_H__
#include <string.h>
class PacketHead
{
public:
typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
PacketHead(uint16 msgId = 0, uint16 bodyLength = 0, uint32 serialNo=0,
uint32 sessionId = 0, uint16 from = 0)
: _msgId(msgId)
, _bodyLength(bodyLength)
, _serialNo(serialNo)
, _sessionId(sessionId)
, _from(from){}
~PacketHead(){}
inline void DecodeHead(const char* buffer)
{
int offset = 0;
memcpy(&_msgId, buffer, sizeof(_msgId));
offset += sizeof(_msgId);
memcpy(&_bodyLength, buffer + offset, sizeof(_bodyLength));
offset += sizeof(_bodyLength);
memcpy(&_serialNo, buffer + offset, sizeof(_serialNo));
offset += sizeof(_serialNo);
memcpy(&_sessionId, buffer + offset, sizeof(_sessionId));
offset += sizeof(_sessionId);
memcpy(&_from, buffer + offset, sizeof(_from));
}
inline void EncodeHead(char* buffer)
{
int offset = 0;
memcpy(buffer, &_msgId, sizeof(_msgId));
offset += sizeof(_msgId);
memcpy(buffer + offset, &_bodyLength, sizeof(_bodyLength));
offset += sizeof(_bodyLength);
memcpy(buffer + offset, &_serialNo, sizeof(_serialNo));
offset += sizeof(_serialNo);
memcpy(buffer + offset, &_sessionId, sizeof(_sessionId));
offset += sizeof(_sessionId);
memcpy(buffer + offset, &_from, sizeof(_from));
}
enum{HeaderLength = 14};
uint16 _msgId;
uint16 _bodyLength;
uint32 _serialNo;
uint32 _sessionId;
uint16 _from;
};
#endif
其中DecodeHead负责解包, EncodeHead负责打包。
同样对于Push而言 需要在发送数据之间进行打包工作,在Pull而言在接受到数据之后进行解包工作。
对于Push一段 需要在Protobuffer序列化之前进行如下操作:
PushZmq* push = new PushZmq(url.c_str());
//string sendContent = "Hello Pull.I am From Push!";
PbMsgHello helloMsg;
helloMsg.set_helloint(123456);
helloMsg.set_hellostring("ni hao wang peng ");
int length = helloMsg.ByteSize();
char* buffer = (char*)malloc(length + PacketHead::HeaderLength);
// 加头
PacketHead packetHead(1,length,2,3,4);
packetHead.EncodeHead(buffer);
helloMsg.SerializeToArray(buffer + PacketHead::HeaderLength, length);
push->Send(buffer, length + PacketHead::HeaderLength);
free(buffer);
对于Pull而言,在接受到的地方进行解包:
LOG(INFO) << "TestOnMessage:";
// 解包
PacketHead packetHead;
packetHead.DecodeHead(buffer);
LOG(INFO) << " msgId = " << packetHead._msgId
<< " bodylength = " << packetHead._bodyLength
<< " serialNo = " << packetHead._serialNo
<<" sessionId = " << packetHead._sessionId
<< " from = " << packetHead._from;
PbMsgHello helloMsg;
helloMsg.ParseFromArray(buffer + PacketHead::HeaderLength, packetHead._bodyLength);
LOG(INFO) << " helloInt = " << helloMsg.helloint()
<< " helloString = " << helloMsg.hellostring();
重新编译运行
Pushl端:
Pull端:
在Pull端可以看到 在Push端之前打包的信息msgId bodyLength等均已解析出来。
打包 解包完毕。 对应源码:http://download.youkuaiyun.com/detail/jcracker/6270973
下一步应该加入framework来处理接受到的消息。