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



>上下文

我正在用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;
}

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

不,这是不可能的。

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

也就是说,这并不像听起来那么糟糕。 请记住,消息的最终解析表示形式(即内存中的消息对象)比线路表示形式大得多。 因此,与以后要处理它的内容相比,您几乎不会在缓冲上浪费内存。 事实上,在实际拥有所有数据之前推迟解析实际上可能会节省内存,因为您不会保留一个大的半解析对象,它只是坐在那里等待数据到达。

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

https://github.com/chrisdew/protostream

相关内容

  • 没有找到相关文章

最新更新