100行解码Protocol Buffers

http://blog.reverberate.org/2008/07/12/100-lines-of-c-that-can-parse-any-protocol-buffer/



/* pb.c -- decode a protobuf into its field numbers and wire values.
 *
 * This decoder does not require a .proto file.  It is equivalent to a
 * generic XML parser, in that it can parse the file, but doesn't know
 * semantically what any of it means.  Also like XML, it doesn't know whether
 * a 32-bit value is an integer or a float, signed or unsigned.  Again, this
 * is much like XML, where you are similarly in the dark if you see a fragment
 * like <foo>332</foo>.
 *
 * Joshua Haberman <joshua@reverberate.org>
 */

#include <stdint.h>
#include <stdio.h>

enum wire_type {
    WT_VARINT = 0,
    WT_64BIT  = 1,
    WT_STRING = 2,
    WT_32BIT  = 5
};

/* Structure representing a tag number and its corresponding wire value.
 * With a .proto file we can refine this data by:
 * - translating field_number -> field_name
 * - translating the wire value into the specific value (ex. 32-bit -> float)
 */
struct key_value_pair
{
    int field_number;
    enum wire_type wire_type;
    union {
      uint64_t varint;
      uint64_t _64_bit;
      struct {
          char *start;
          int len;
      } string;
      uint32_t _32_bit;
    } value;
};

/* A callback that is called every time we parse a key/value pair */
typedef void (*yield_t)(struct key_value_pair*);

uint64_t decode_varint(char *buf, char **end)
{
    uint64_t ret = 0;
    int bitpos = 0;
    for(int bitpos = 0; *buf & 0x80 && bitpos < 64; bitpos += 7, buf++)
        ret |= (*buf & 0x7F) << bitpos;
    ret |= (*buf & 0x7F) << bitpos;
    *end = buf+1;
    return ret;
}

uint32_t get_32_le(char *buf, char **end)
{
    *end = buf+4;
    return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
}

void decode_protobuf(char *buf, char *buf_end, yield_t yield)
{
    while(buf < buf_end)
    {
        uint64_t key = decode_varint(buf, &buf);
        struct key_value_pair pair = {
            .field_number = key >> 3,
            .wire_type = key & 0x07
        };
        switch(pair.wire_type)
        {
            case WT_VARINT:  /* varint */
                pair.value.varint = decode_varint(buf, &buf);
                break;

            case WT_64BIT:  /* 64 bit */
                pair.value._64_bit = get_32_le(buf, &buf);
                buf += 4;
                pair.value._64_bit |= (uint64_t)get_32_le(buf, &buf) << 32;
                buf += 4;
                break;

            case WT_STRING:  /* string */
                pair.value.string.len = decode_varint(buf, &buf);
                pair.value.string.start = buf;
                buf += pair.value.string.len;
                break;

            case WT_32BIT:  /* 32 bit */
                pair.value._32_bit = get_32_le(buf, &buf);
                buf += 4;
                break;
        }

        yield(&pair);
    }
}

void yield_cb(struct key_value_pair *pair)
{
    printf("Field number: %d, Wire type: %d\n", pair->field_number,
                                                pair->wire_type);
}

int main()
{
    char pb_1[] = {0x12, 0x07, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67};
    char pb_2[] = {0x08, 0x96, 0x01};
    decode_protobuf(pb_1, pb_1+sizeof(pb_1), yield_cb);
    decode_protobuf(pb_2, pb_2+sizeof(pb_2), yield_cb);
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 您好,我可以提供一个同时支持JMeter测试MQTT协议和Google Protocol Buffers协议的插件,它是MQTT Protocol Plugin for JMeter。该插件可以通过添加MQTT协议支持来扩展JMeter的功能,并提供了与Google Protocol Buffers协议的兼容性。 该插件可以通过JMeter插件管理器安装。安装后,您可以使用它来创建MQTT测试计划,并在测试计划中使用Google Protocol Buffers协议进数据交换。希望这对您有所帮助! ### 回答2: 目前,JMeter并没有提供官方的插件来测试MQTT协议和Google Protocol Buffers协议。但是,我们可以通过使用第三方插件来实现这个目标。 要测试MQTT协议,可以使用Eclipse Paho插件。Paho是一个开源的MQTT客户端库,它提供了多种编程语言的实现。要在JMeter中使用Paho插件,首先需要下载Paho的Java实现。然后将相关的JAR文件添加到JMeter的classpath中。使用JMeter的Java Request Sampler可以使用Paho库编写自定义的Java代码来测试MQTT协议。 要测试Google Protocol Buffers协议,可以使用jmeter-protobuf插件。这个插件是一个JMeter的定制扩展,可以与Google Protocol Buffers集成。要使用该插件,首先需要将jmeter-protobuf插件的JAR文件添加到JMeter的lib/ext目录中。接下来,在JMeter中创建一个ProtoBuf PreProcessor和一个ProtoBuf PostProcessor,这样就可以在发送和接收请求之前和之后对数据进编码和解码。 使用这两个插件,你可以在JMeter中编写和执MQTT和Google Protocol Buffers测试计划。但是,请注意,这些插件需要一定的配置和编程知识来正确使用。建议查阅官方文档和示例代码,以确保正确地配置和使用插件。 总结而言,要同时测试MQTT协议和Google Protocol Buffers协议,可以使用第三方插件Eclipse Paho和jmeter-protobuf。这些插件需要额外的配置和编程知识,所以一定要仔细阅读和理解官方文档和示例代码。 ### 回答3: 目前,我所知道的一个同时用于JMeter测试MQTT协议和Google Protocol Buffers协议的插件是Eclipse Paho插件。 Eclipse Paho是一个开源的MQTT客户端库,它提供了用于连接、发布和订阅MQTT消息的API。通过集成Eclipse Paho插件,我们可以在JMeter中实现MQTT协议的测试。 同时,Google Protocol Buffers是一种跨平台、语言无关的数据序列化机制,它可以在不同的平台和环境中进数据交换。我们可以通过使用JMeter的扩展插件,如gRPC插件或Protobuf插件,来支持Google Protocol Buffers协议的测试。 要同时使用JMeter进MQTT协议和Google Protocol Buffers协议的测试,我们可以按照以下步骤操作: 1. 下载和安装JMeter插件管理器,使我们能够方便地管理和安装JMeter的扩展插件。 2. 在JMeter插件管理器中搜索并安装Eclipse Paho插件,这样我们就可以使用该插件进MQTT协议的测试。 3. 同样地,在JMeter插件管理器中搜索并安装gRPC插件或Protobuf插件,这样我们就可以使用其中的功能来支持Google Protocol Buffers协议的测试。 4. 在JMeter中创建测试计划,并添加MQTT Sampler和Protobuf Sampler来模拟相应的MQTT和Google Protocol Buffers请求。 5. 配置Sampler的参数,如服务器地址、端口号、订阅主题、发送的消息等等,以便进相应的测试。 6. 运测试计划,观察并分析测试结果,以评估系统在处理MQTT和Google Protocol Buffers协议时的性能。 总之,通过集成Eclipse Paho插件和适当的JMeter扩展插件,我们可以实现同时测试MQTT和Google Protocol Buffers协议的功能,并评估系统的性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值