protobuf 如何解析(大于64MB)超大报文

为了阻止恶意用户发送超大报文,而导致int溢出或服务端为解析报文而分配大量内存致使内存耗尽,protobuf规定int溢出的默认值阈值是64MB(理论是512MB)。因此,当调用ParseFromString(str)方法时,若str的长度>64MB,返回会返回失败。

注意到protobuf中包含这样一个函数:void SetTotalBytesLimit(int total_bytes_limit, int warning_threshold),其中有解释如下:

这里写图片描述

解决方法

    LoadDBDataProtobuf::DocumentData pDocumentData; // LoadDBDataProtobuf::DocumentData为应用程序自定义的protobuf结构

    ::google::protobuf::io::ArrayInputStream input(strData.data(), strData.size()); //std::string strData,是响应报文中mTOM构造出而来
    ::google::protobuf::io::CodedInputStream decoder(&input);
    decoder.SetTotalBytesLimit(1024 * 1024 * 1024, 64 * 1024 * 1024);
    bool success = pDocumentData.ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage();

    if (!success)
    {
        SvrResponse::instance()->setCurrentThreadReturnCode(eOtherErr, QString("protoBuf序列化出错"));
        return false;
    }

ZeroCopyInputStream 类

class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream
{
 public:

    // 构造一个InputStream,返回data所指向的字节数组
    // 若指定了block_size,则每次调用Next()返回不超过指定大小的数据块;否则,返回整个字节数组
    ArrayInputStream(const void* data, int size, int block_size = -1);

    ~ArrayInputStream();

    // implements ZeroCopyInputStream ----------------------------------
     bool Next(const void** data, int* size);

    ......

  }

CodedInputStream 类

class LIBPROTOBUF_EXPORT CodedInputStream 
{
public:

    // 构造一个从ZeroCopyInputStream读取数据的CodedInputStream对象
    explicit CodedInputStream(ZeroCopyInputStream* input);

    // total_bytes_limit:可读取的最大报文字节数
    // warning_threshold:发出警告的最大报文字节数,若不为-1,则当读取的字节数超过warning_threshold后,stderr将会打印一条警告消息。
    void SetTotalBytesLimit(int total_bytes_limit, int warning_threshold)

    // 当对报文进行解析后,必须调用ConsumedEntireMessage,以进一步判断报文是否被以正确方式读取完毕。
    bool ConsumedEntireMessage()

......

}

ParseFromCodedStream(io::CodedInputStream* input)

功能:从给定的CodedInputStream对象中解析数据。
返回值:false,CodedInputStream格式错误或其他读错误。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值