将数据流式传输到protobuf解析器c ++

时间:2014-02-23 21:22:20

标签: c++ event-handling protocol-buffers

上下文

我正在用C ++编写一个事件驱动的应用程序服务器。我想使用谷歌协议缓冲区来移动我的数据。由于服务器是事件驱动的,连接处理程序API基本上是一个回调函数,让我知道N字节的另一个缓冲区何时从客户端到达。

问题

我作为protobuf的完全初学者的问题是:是否有可能以某种方式哄骗protobuf接受构成一个完整消息所需的许多缓冲区以促进“流解析器”而不是等待整个数据到达首先是一个临时缓冲区?

换句话说,我想要这个:

//Event API. May be called multiple times for each protobuf message
bool data_arrived_from_client(void *buf,size_t len){
    my_protobuf.parse_part(buf,len); // THIS IS THE GROSSLY SIMPLIFIED SEMANTIC OF WHAT I WANT
    message_size+=len;
    if(message_size>COMPLETE_BUFFER_SIZE){
        use_complete_protobuf();
        return true;
    }
    return false;
}

..而不是:

//Event API. May be called multiple times for each protobuf message
bool data_arrived_from_client(void *buf,size_t len){
    my_temp_buffer.append_data(buf,len);
    message_size+=len;
    if(message_size>COMPLETE_BUFFER_SIZE){
        my_protobuf.ParseFromArray(my_temp_buffer.data_ptr(),my_temp_buffer.size());
        use_complete_protobuf();
        return true;
    }
    return false;
}

答案

特别感谢完整代码的答案!

2 个答案:

答案 0 :(得分:1)

不,这是不可能的。

Protobuf解析器是一个递归下降解析器,意味着它的很多状态都存储在堆栈中。这使得它很快,但这意味着除了暂停整个线程之外,没有办法暂停中间的解析器。如果您的应用程序是非阻塞的,那么您只需缓冲字节,直到您要解析整个消息。

那就是说,这并不像听起来那么糟糕。请记住,消息的最终解析表示(即内存中消息对象)大于线表示。因此,与稍后用它做的事情相比,你几乎不会在缓冲上浪费记忆。实际上,在实际拥有所有数据之前,暂缓解析可能实际上节省了内存,因为你没有抓住那个只是坐在那里等待数据到达的大型半解析对象。

答案 1 :(得分:1)

是的,这是可能的,我已经在Javascript中完成了,但设计可以​​移植到C ++。

https://github.com/chrisdew/protostream