使用 nodejs 上的 protobufjs 使用来自 .net 的 protobuf 消息时,无效的线路类型和索引超出范围错误
Invalid wire type and index out of range errors when consuming a protobuf message from .net with protobufjs on nodejs
我正在尝试在节点 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 通道。
但我总是遇到以下错误之一:
偏移量 2 处的线类型 7 无效
偏移量 2 处的线类型 4 无效
偏移量 2 处的线类型 6 无效
索引超出范围:237 + 10 > 237
等等
我做错了什么?
编辑:
看来我没有考虑到 MessageBase(PositionOpenNotification 继承的抽象)也是一个 ProtoContract 并且数据是用长度前缀序列化的。
所以最后这是有效的:
添加一个包含 PositionOpenNotification 对象的 MessageBase 对象:
@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 不存在,因此:错误至少是正确的。
此类错误通常表明负载在传输过程中已损坏。最常见的做法是将其视为文本,和/或(非常频繁地看到的东西):运行 通过向后编码以通过文本协议传输二进制数据。检查你没有这样做。基本上,您需要在两端获得完全相同的字节;在你拥有它之前,其他任何东西都不起作用。特别是,如果您需要通过文本协议传输二进制文件:base-64 是您的朋友。
附带说明:protobuf-net 具有为您的对象模型导出 .proto 模式的方法,使 x-plat 更加方便。寻找 Serializer.GetProto<T>
.
如果您有不确定的负载,您可以使用 https://protogen.marcgravell.com/decode 来验证和检查二进制数据。
我正在尝试在节点 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 通道。
但我总是遇到以下错误之一:
偏移量 2 处的线类型 7 无效
偏移量 2 处的线类型 4 无效
偏移量 2 处的线类型 6 无效
索引超出范围:237 + 10 > 237
等等
我做错了什么?
编辑:
看来我没有考虑到 MessageBase(PositionOpenNotification 继承的抽象)也是一个 ProtoContract 并且数据是用长度前缀序列化的。
所以最后这是有效的:
添加一个包含 PositionOpenNotification 对象的 MessageBase 对象:
@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 不存在,因此:错误至少是正确的。
此类错误通常表明负载在传输过程中已损坏。最常见的做法是将其视为文本,和/或(非常频繁地看到的东西):运行 通过向后编码以通过文本协议传输二进制数据。检查你没有这样做。基本上,您需要在两端获得完全相同的字节;在你拥有它之前,其他任何东西都不起作用。特别是,如果您需要通过文本协议传输二进制文件:base-64 是您的朋友。
附带说明:protobuf-net 具有为您的对象模型导出 .proto 模式的方法,使 x-plat 更加方便。寻找 Serializer.GetProto<T>
.
如果您有不确定的负载,您可以使用 https://protogen.marcgravell.com/decode 来验证和检查二进制数据。