7. 对通信数据包进行打包

在章节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.csdn.net/detail/jcracker/6270973

下一步应该加入framework来处理接受到的消息。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值