protobuf-csharp-端口

发布于 2024-09-15 23:44:21 字数 1489 浏览 1 评论 0原文

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

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

message InstantMessage {<br/>
  required string Message = 1;<br/>
  required int64 TimeStampTicks = 2; <br/>
}

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

        ...
        InstantMessage.Builder imBuild = new InstantMessage.Builder();

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

        InstantMessage im = imBuild.BuildPartial();

        im.WriteTo(networkStream);
        ...

这非常有效。但在另一端,我无法让 ParseFrom 正常工作。

我想使用:-

InstantMessage im = InstantMessage.ParseFrom(networkStream);

但我必须将其读取为字节,然后从这里解析它。由于多种原因,这显然并不理想。当前代码是:-

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

I'm using Jon Skeet's (excellent) port of Google's Protocol Buffers to C#/.Net.

For practice, I have written a dummy Instant Messenger app that sends some messages down a socket. 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.

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.

Any advice would be gratefully received,

PW

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉风有信 2024-09-22 23:44:21

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

现在有另一个 API 可以执行此操作:IMessage.WriteDelimitedToIBuilder.MergeDelimitedFrom。这可能是您目前想要的,但我似乎记得在检测流的结尾方面有一个小问题(即,当没有其他消息可供读取时)。我不记得目前是否有修复程序 - 我感觉它在 Java 版本中发生了变化,而且我可能还没有移植该更改。无论如何,这绝对是值得关注的领域。

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. 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).

There's now another API to do this: IMessage.WriteDelimitedTo and 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 (i.e. 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. Anyway, that's definitely the area to look at.

戒ㄋ 2024-09-22 23:44:21

Protobuf 没有终止符 - 因此要么关闭流,要么使用您自己的长度前缀等。Protobuf-net 通过 SerializeWithLenghtPrefix / DeserializeWithLengthPrefix 轻松公开这一点。

简单地说:如果没有这个,它就无法知道每条消息在哪里结束,因此不断尝试读取到流的末尾。

Protobuf has no terminator - so either close the stream, or use your own length prefix etc. Protobuf-net exposes this easily via SerializeWithLenghtPrefix / DeserializeWithLengthPrefix.

Simply: without this, it can't know where each message ends, so keeps trying to read to the end of the stream.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文