Google协议缓冲区:c++的parseDelimitedFrom和writeDelimitedTo
Google Protocol Buffers: parseDelimitedFrom and writeDelimitedTo for C++
很抱歉再次问这个问题,但是我们能不能一劳永逸地在这里发布一些与Java函数匹配的c++函数?它们似乎不是由谷歌添加的,而且自己编写它们是相当痛苦的。
下面是使用boost asio的两个基本版本。注意,为了正常工作,从技术上讲,在第二版中,一个需要看多少数据缓冲区,工作头有多大(VarInt不是一个固定的大小),但CodedInputStream GetDirectBufferPointer,指针指向的地方,所以从这个指针可以解决剩下的消息大小,比较它与给定的消息大小,构造一个新的调整缓冲剩余的大小,和做一个asio同步读取的消息。只要消息保持小(我猜大约1 kb左右),下面的工作。如果有人知道丢失的部分,请大声说出来。谢谢。
writeDelimitedTo in c++:
boost::asio::streambuf request;
{
std::ostream request_stream(&request);
google::protobuf::io::OstreamOutputStream raw_output (&request_stream);
google::protobuf::io::CodedOutputStream coded_output(&raw_output);
coded_output.WriteVarint32(myProtoMsg.ByteSize());
myProtoMsg.SerializeToCodedStream(&coded_output);
}
boost::asio::write(socket,request);
parseDelimitedFrom:
char buf[5000];
void Session::Read()
{
boost::asio::async_read(
socket,
boost::asio::buffer(buf),
boost::asio::transfer_at_least(1),
boost::bind(&Session::Handle_Read,shared_from_this(),boost::asio::placeholders::error));
}
void Session::Handle_Read(const boost::system::error_code& error)
{
if (!error)
{
google::protobuf::io::ArrayInputStream arrayInputStream(buf,5000);
google::protobuf::io::CodedInputStream codedInputStream(&arrayInputStream);
uint32_t messageSize;
codedInputStream.ReadVarint32(&messageSize);
//Read more here
MyProtoMsg myProtoMsg;
myProtoMsg.ParseFromCodedStream(&codedInputStream);
}
Read();
}
编辑:上面有点懒(在这里阅读更多)。下面是一个完整的parseDelimitedFrom。
新parseDelimitedFrom:
static void ReadMyVarint32(int& headerSize,int& messageSize,char buffer[])
{
// Fast path: We have enough bytes left in the buffer to guarantee that
// this read won't cross the end, so we can skip the checks.
char const* ptr = buffer;
char b;
uint32_t result;
b = *(ptr++); result = (b & 0x7F) ; if (!(b & 0x80)) goto done;
b = *(ptr++); result |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
b = *(ptr++); result |= b << 28; if (!(b & 0x80)) goto done;
// If the input is larger than 32 bits, we still need to read it all
// and discard the high-order bits.
for (int i = 0; i < 5; i++) {
b = *(ptr++); if (!(b & 0x80)) goto done;
}
// We have overrun the maximum size of a varint (10 bytes). Assume
// the data is corrupt.
headerSize = 0;
messageSize = 0;
done:
headerSize = ptr - buffer;
messageSize = (int)result;
}
char buf[5000];
int receivedSize(0);
int missingSize(0);
void Session::Read()
{
boost::asio::async_read(
socket,
boost::asio::buffer(buf),
boost::asio::transfer_at_least(1),
boost::bind(&Session::Handle_Read,shared_from_this(),_1,_2));
}
void Session::Handle_Read(const boost::system::error_code& error,std::size_t bytes_transferred)
{
if (!error)
{
int mybytes_transferred((int)bytes_transferred);
if(missingSize == 0)
{
int headerSize, messageSize;
ReadMyVarint32(headerSize,messageSize,buf);
//std::cout << "Read new message: HeaderSize " << headerSize << " MessageSize " << messageSize << " Received: " << mybytes_transferred << std::endl;
for(int i(0);i<mybytes_transferred-headerSize;++i)
request[i] = buf[headerSize+i];
missingSize = headerSize + messageSize - mybytes_transferred;
receivedSize = mybytes_transferred - headerSize;
}
else
{
//std::cout << "Continue message: Read so far " << receivedSize << " Missing " << missingSize << " Received: " << mybytes_transferred << std::endl;
for(int i(0);i<mybytes_transferred;++i)
request[receivedSize+i] = buf[i];
missingSize -= mybytes_transferred;
receivedSize += mybytes_transferred;
}
if(missingSize < 0)
{
//Received too much, give up
missingSize = 0;
receivedSize = 0;
}
else if(missingSize == 0)
{
// Use your proto class here
RequestWrapperPtr requestWrapperPtr(new RequestWrapper());
if(requestWrapperPtr->ParseFromArray(request,receivedSize))
{
HandleRW(requestWrapperPtr);
}
else
{
// std::cout << BaseString() << "Session Handle_Read: Failed to parse!";
}
}
Read();
}
}
我知道这个问题已经得到了回答,但是这个问题现在已经非常老了,并且从那时起已经对protobuf代码存储库进行了更新。
Protobuf现在在头文件下面有这些函数:
#include <google/protobuf/util/delimited_message_util.h>
您可以在这里的git仓库中查看相关的cpp
文件。我已经用boost插座尝试了这些函数,它们按预期工作。
相关文章:
- 没有找到相关文章