上下文
我正在用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;
}
答案
特别感谢完整代码的答案!
答案 0 :(得分:1)
不,这是不可能的。
Protobuf解析器是一个递归下降解析器,意味着它的很多状态都存储在堆栈中。这使得它很快,但这意味着除了暂停整个线程之外,没有办法暂停中间的解析器。如果您的应用程序是非阻塞的,那么您只需缓冲字节,直到您要解析整个消息。
那就是说,这并不像听起来那么糟糕。请记住,消息的最终解析表示(即内存中消息对象)多大于线表示。因此,与稍后用它做的事情相比,你几乎不会在缓冲上浪费记忆。实际上,在实际拥有所有数据之前,暂缓解析可能实际上节省了内存,因为你没有抓住那个只是坐在那里等待数据到达的大型半解析对象。
答案 1 :(得分:1)
是的,这是可能的,我已经在Javascript中完成了,但设计可以移植到C ++。