首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >协议port csharp-port

协议port csharp-port
EN

Stack Overflow用户
提问于 2010-08-27 23:12:36
回答 2查看 1.9K关注 0票数 4

我正在使用Jon Skeet的(出色的)Google的Protocol Buffers移植到C#/.Net。

作为练习,我编写了一个虚拟的即时消息应用程序,它通过套接字发送一些消息。我有一个消息定义如下:

代码语言:javascript
复制
message InstantMessage {<br/>
  required string Message = 1;<br/>
  required int64 TimeStampTicks = 2; <br/>
}

当发送者序列化消息时,它会非常优雅地发送消息:

代码语言:javascript
复制
        ...
        InstantMessage.Builder imBuild = new InstantMessage.Builder();

        imBuild.Message = txtEnterText.Text;
        imBuild.TimeStampTicks = DateTime.Now.Ticks;

        InstantMessage im = imBuild.BuildPartial();

        im.WriteTo(networkStream);
        ...

这很好用。但在另一端,我无法让ParseFrom正常工作。

我想使用:-

代码语言:javascript
复制
InstantMessage im = InstantMessage.ParseFrom(networkStream);

但是我不得不把它读成字节,然后从这里解析它。这显然并不理想,原因有很多。当前代码是:-

代码语言:javascript
复制
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());

当我尝试使用ParseFrom时,即使我知道网络上有一个有效的GB消息,控制也不会返回到调用方法。

我们将非常感谢您的建议,

PW

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-08-30 16:41:41

很抱歉花了一段时间来回答这个问题。正如Marc所说,协议缓冲区没有终止符,除非它们是嵌套的,否则它们不会有长度前缀。但是,您可以自己添加长度前缀。如果你看看MessageStreamIterator和MessageStreamWriter,你就会明白我是如何做到这一点的--基本上,我假装我在一条消息的中间,将一个嵌套的消息写成字段1。不幸的是,在读取消息时,我不得不使用内部细节(BuildImpl)。

现在有另一个API可以做到这一点:IMessage.WriteDelimitedToIBuilder.MergeDelimitedFrom。这可能是你现在想要的,但我记得它在检测流的结尾方面有一个小问题(即当没有另一条消息可读时)。我不记得目前是否有修复--我有一种感觉,它在Java版本中已经改变了,我可能还没有移植这个改变。无论如何,这绝对是值得关注的领域。

票数 4
EN

Stack Overflow用户

发布于 2010-08-27 23:58:33

Protobuf没有终止符-所以要么关闭流,要么使用自己的长度前缀等。Protobuf-net很容易通过SerializeWithLenghtPrefix / DeserializeWithLengthPrefix公开这一点。

简单地说:如果没有这个,它就不能知道每个消息在哪里结束,所以一直尝试读到流的末尾。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3585562

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档