node.js - 在 Nodejs 上使用 protobufjs 使用来自 .net 的 protobuf 消息时出现无效的线路类型和索引超出范围错误

标签 node.js protocol-buffers protobuf-net protobuf.js node-amqplib

我正在尝试在 Node js 上使用来自 RMQ 的 protobuf 消息。 protobuf 消息是在 C#.Net 上使用 protobuf-net 创建的

例如,c# 对象如下所示:

    [ProtoContract]
    public class PositionOpenNotification : MessageBase
    {
    [ProtoMember(1)]
    public int PositionID { get; set; }

    [ProtoMember(2)]
    public int InstrumentID { get; set; }
    ..
    ..Down to tag 30

然后将其添加到 RMQ,并且我们在另一端使用具有相同对象的 .net 监听器来对其进行解码。

但是现在我们想从nodejs读取消息。 为此,我在 Nodejs 端使用 amqplib 和 protobuf-js。

我试图使用带有这样的装饰器的对象来解码消息:

import { Message, Type, Field } from "protobufjs/light"; 
 
 @Type.d("PositionOpenNotification")
 export class PositionOpenNotification extends Message<PositionOpenNotification> {
 
  @Field.d(1,"int32", "required")
  public PositionID: number;
}

解码如下:

ch.consume(q.queue, function(msg, res) {
            try {
                if(msg.content) {
                    let decoded = PositionOpenNotification.decode( msg.content);
                    console.log(" Received %s", decoded,q.queue);
                }
              } catch (e) {
                 console.log("Error  %s ", e.message)
              }
        }

其中 ch 是 amqplib RMQ channel 。

但我总是遇到以下错误之一:

偏移量 2 处的线类型 7 无效

偏移 2 处的线类型 4 无效

偏移 2 处的线类型 6 无效

索引超出范围:237 + 10 > 237

等等

我做错了什么?

编辑:

看来我没有考虑到 MessageBase(PositionOpenNotification 继承的抽象)也是一个 ProtoContract 并且数据是用长度前缀序列化的事实。

所以最后这就是有效的:

添加一个 MessageBase 对象,其中包含 PositionOpenNotification 对象:

@Type.d("MessageBase")
export class MessageBase extends Message<MessageBase> {

  @Field.d(108, PositionOpenNotification)
  public positionOpenNotification: PositionOpenNotification;
}

然后反序列化时:

 if(msg.content) {
    var reader = Reader.create(msg.content);
    let decoded = MessageBase.decodeDelimited(reader);
 }

最佳答案

电线类型 7 不存在,因此:至少错误是正确的。

这种类型的错误通常表明有效负载在传输过程中已损坏。最常见的方法是将其视为文本和/或(非常频繁地看到的东西):通过向后编码运行它以通过文本协议(protocol)传输二进制数据。检查一下你是否没有这样做。基本上,您需要在两端获得完全相同的字节;在你做到这一点之前,其他任何事情都行不通。特别是,如果您需要通过文本协议(protocol)传输二进制文件:base-64 是您的 friend 。

作为旁注:protobuf-net 有方法为您的对象模型导出 .proto 架构,以使 x-plat 更加方便。寻找Serializer.GetProto<T> .

如果您不确定有效负载,可以使用 https://protogen.marcgravell.com/decode验证和检查二进制数据。

关于node.js - 在 Nodejs 上使用 protobufjs 使用来自 .net 的 protobuf 消息时出现无效的线路类型和索引超出范围错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62513177/

相关文章:

c - 服务器多线程,协议(protocol)必须?和更多

c++ - 使用 Protocol Buffers 从文件中读取消息的问题

c# - 在 ProtoBuf-net 中序列化 Dictionary<string,object> 失败

c# - 使用 protobuf-net 为 c# 生成的文件与在 C++ 中生成的相同文件略有不同

heroku 上的 node.js : Error: Cannot find module 'csv'

Javascript——在 Node.js 和浏览器中导出

node.js - RethinkDB/地平线 : Integration with Express: Access Horizon data server-side?

node.js - 规模 SocketIO (NowJS)

c - nanopb( Protocol Buffer 库)重复子消息编码

.net - 我可以使用 protobuf-net 在 Mono 中序列化一个对象(包含成员 : Dictionary, 列表...等)并在 MS.NET 中反序列化它,反之亦然?