[英]protobuf-csharp-port
I'm using Jon Skeet's (excellent) port of Google's Protocol Buffers to C#/.Net. 我正在使用Jon Skeet的(优秀)谷歌协议缓冲区端口到C#/ .Net。
For practice, I have written a dummy Instant Messenger app that sends some messages down a socket. 为了练习,我编写了一个虚拟的Instant Messenger应用程序,它可以在套接字上发送一些消息。 I have a message definition as follows:-
我的消息定义如下: -
message InstantMessage {<br/>
required string Message = 1;<br/>
required int64 TimeStampTicks = 2; <br/>
}
When the sender serialises the message, it sends it really elegantly:- 当发件人序列化邮件时,它会非常优雅地发送邮件: -
...
InstantMessage.Builder imBuild = new InstantMessage.Builder();
imBuild.Message = txtEnterText.Text;
imBuild.TimeStampTicks = DateTime.Now.Ticks;
InstantMessage im = imBuild.BuildPartial();
im.WriteTo(networkStream);
...
This works great. 这非常有效。 But at the other end, I'm having trouble getting the
ParseFrom
to work. 但另一方面,我无法让
ParseFrom
工作。
I want to use:- 我想用: -
InstantMessage im = InstantMessage.ParseFrom(networkStream);
But instead I have had to read it to bytes and then parse it from here. 但相反,我必须将其读取为字节,然后从此处解析它。 This is obviously not ideal for a number of reasons.
出于多种原因,这显然不是理想的。 Current code is:-
目前的代码是: -
while (true)
{
Byte[] byteArray = new Byte[10000000];
int intMsgLength;
int runningMsgLength = 0;
DateTime start = DateTime.Now;
while (true)
{
runningMsgLength += networkStream.Read(byteArray, runningMsgLength, 10000000 - runningMsgLength);
if (!networkStream.DataAvailable)
break;
}
InstantMessage im = InstantMessage.ParseFrom(byteArray.Take(runningMsgLength).ToArray());
When I try to use ParseFrom
, control does not return to the calling method even when I know a valid GB message is on the wire. 当我尝试使用
ParseFrom
,即使我知道有线GB消息ParseFrom
,控制也不会返回到调用方法。
Any advice would be gratefully received, 任何建议都会感激不尽,
PW PW
Sorry for taking a while to answer this. 很抱歉花了一些时间来回答这个问题。 As Marc says, protocol buffers don't have a terminator, and they aren't length prefixed unless they're nested.
正如Marc所说,协议缓冲区没有终结符,除非它们是嵌套的,否则它们不是长度前缀。 However, you can put on the length prefix yourself.
但是,您可以自己加上长度前缀。 If you look at MessageStreamIterator and MessageStreamWriter, you'll see how I do this - basically I pretend that I'm in the middle of a message, writing a nested message as field 1. Unfortunately when reading the message, I have to use internal details (BuildImpl).
如果你看一下MessageStreamIterator和MessageStreamWriter,你会看到我是怎么做的 - 基本上我假装我正处于消息中间,将嵌套消息写成字段1.不幸的是,在阅读消息时,我必须使用内部细节(BuildImpl)。
There's now another API to do this: IMessage.WriteDelimitedTo
and IBuilder.MergeDelimitedFrom
. 现在有另外一个API来执行此操作:
IMessage.WriteDelimitedTo
和IBuilder.MergeDelimitedFrom
。 This is probably what you want at the moment, but I seem to remember there's a slight issue with it in terms of detecting the end of the stream (ie when there isn't another message to read). 这可能是你现在想要的,但我似乎记得它在检测流的结束方面存在一个小问题(即,当没有其他消息要读取时)。 I can't remember whether there's a fix for it at the moment - I have a feeling it's changed in the Java version and I may not have ported the change yet.
我不记得目前是否有一个修复程序 - 我感觉它在Java版本中已经改变了,我可能还没有移植过这个改变。 Anyway, that's definitely the area to look at.
无论如何,这绝对是值得关注的领域。
Protobuf has no terminator - so either close the stream, or use your own length prefix etc. Protobuf-net exposes this easily via SerializeWithLenghtPrefix / DeserializeWithLengthPrefix. Protobuf没有终止符 - 所以要么关闭流,要么使用自己的长度前缀等.Protobuf-net通过SerializeWithLenghtPrefix / DeserializeWithLengthPrefix轻松暴露这个。
Simply: without this, it can't know where each message ends, so keeps trying to read to the end of the stream. 简单地说:没有它,它无法知道每条消息的结束位置,因此不断尝试读取到流的末尾。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.