C# protobuf网与重复场
在protobuf中使用列表作为重复字段的对应项是否正确?我正在尝试这个,但总是出现异常: 导线类型无效;这通常意味着您在没有截断或设置长度的情况下重写了文件;看 整个缓冲区是(第一个消息,下一个到达的消息附加到此消息): 985262423898321 java protobuf文件:C# protobuf网与重复场,c#,java,protocol-buffers,protobuf-net,C#,Java,Protocol Buffers,Protobuf Net,在protobuf中使用列表作为重复字段的对应项是否正确?我正在尝试这个,但总是出现异常: 导线类型无效;这通常意味着您在没有截断或设置长度的情况下重写了文件;看 整个缓冲区是(第一个消息,下一个到达的消息附加到此消息): 985262423898321 java protobuf文件: package XXX; option java_package = "XXX"; option java_outer_classname = "Protos"; option optimize_for =
package XXX;
option java_package = "XXX";
option java_outer_classname = "Protos";
option optimize_for = SPEED;
message V3DDelta {
optional int32 bid = 1;
optional int32 bidSize = 2;
optional int32 ask = 3;
optional int32 askSize = 4;
}
message Request {
optional int32 type = 1;
optional string request = 2;
}
message Response {
optional int32 type = 1;
optional string response = 2;
repeated V3DDelta v3dDelta = 3;
}
和protbuf网络类:
[ProtoContract]
public class V3DDelta {
[ProtoMember(1)]
public double bid { get; set; }
[ProtoMember(2)]
public int bidSize { get; set; }
[ProtoMember(3)]
public double ask { get; set; }
[ProtoMember(4)]
public int askSize { get; set; }
}
[ProtoContract]
public class Request {
[ProtoMember(1)]
public int Type { get; set; }
[ProtoMember(2)]
public string Rq { get; set; }
}
[ProtoContract]
public class Response {
[ProtoMember(1)]
public int Type { get; set; }
[ProtoMember(2)]
public string Rsp { get; set; }
[ProtoMember(3)]
public List<V3DDelta> v3dDelta { get; set; }
public Response() {
v3dDelta = new List<V3DDelta>();
}
}
[协议]
公共类V3DDelta{
[原成员(1)]
公共双标{get;set;}
[原成员(2)]
公共整数bidSize{get;set;}
[原成员(3)]
公共双询问{get;set;}
[原成员(4)]
public int askSize{get;set;}
}
[原始合同]
公共类请求{
[原成员(1)]
公共int类型{get;set;}
[原成员(2)]
公共字符串Rq{get;set;}
}
[原始合同]
公众课堂反应{
[原成员(1)]
公共int类型{get;set;}
[原成员(2)]
公共字符串Rsp{get;set;}
[原成员(3)]
公共列表v3dDelta{get;set;}
公众回应({
v3dDelta=新列表();
}
}
我尝试了V3DDelta[],但结果是一样的。
阅读信息:
Response rsp = Serializer.DeserializeWithLengthPrefix<Response>(rcvstream, PrefixStyle.Base128);
Response rsp=Serializer.DeserializeWithLengthPrefix(rcvstream,PrefixStyle.Base128);
在java中,消息是使用writeDelimitedTo发送的。
c#中的缓冲区与java中的完全相同。
当有一个v3dDelta字段时,一切都按预期工作。是的,列表
或数组(T[]
)将用于重复
。顺便提一下,有一个工具可以从.proto定义生成protobuf网络类
您试图“使用长度前缀”读取它,但是:9作为变量前缀无效(9
,作为字段标题,意味着“字段1,固定64位数据”,但是:在此上下文中,它应该是变量)
实际上,none数据与9
作为字段头是兼容的,因为在字段1
的定义中没有任何64位值。您确实有一个double
作为字段3
,这将很好地完成这项工作-但是,这将是73
作为字段标题
我会告诉你序列9,8,5,。。。然而,代表-我们将:
9 : field 1, fixed 64-bit
8 5 26 5 24 238 98 32 <== payload for above
1 : field 0, fixed 64-bit
^^ not *really* valid, but fields <= 0 generally mean "stop" - but
frankly this is not a clean/defined/expected exit condition
这给了我们9
,我们还有9
字节,所以看起来不错
8 : Field 1, varint
5 = payload of above
26 : Field 3, length-delimited
5 = length of payload
24 238 98 32 1 = payload of ^^^
24 : Field 3, varint
238, 98 = payload of ^^^ = 12654
32 : Field 4, varint
1 = payload of ^^^ = 1
现在看起来它应该解析。。。调查为什么不是
编辑2:经过一点调试后,部分原因是您(很抱歉)损坏了
v3ddeta
属性。您在proto中将它们定义为int32
(字段3是数据中的变量),但您将它们实现为double
。。。和double
和int32
不是朋友
因此:
然后,以下方法可以很好地工作:
using (var ms = new MemoryStream(buffer))
{
int len = ProtoReader.DirectReadVarintInt32(ms);
var resp = (Response)model.Deserialize(ms, null, typeof(Response), len);
Assert.AreEqual(5, resp.Type);
Assert.AreEqual(1, resp.v3dDelta.Count);
Assert.AreEqual(12654, resp.v3dDelta[0].ask);
Assert.AreEqual(1, resp.v3dDelta[0].askSize);
}
从技术上讲,我可以让protobuf net接受一个varint
值作为double
值,但这高度表明模式并不真正匹配,因此我认为正确的做法是在这种情况下更改类型。是的,List
或数组(t[]
)将适用于重复的。顺便提一下,有一个工具可以从.proto定义生成protobuf网络类
您试图“使用长度前缀”读取它,但是:9作为变量前缀无效(9
,作为字段标题,意味着“字段1,固定64位数据”,但是:在此上下文中,它应该是变量)
实际上,none数据与9
作为字段头是兼容的,因为在字段1
的定义中没有任何64位值。您确实有一个double
作为字段3
,这将很好地完成这项工作-但是,这将是73
作为字段标题
我会告诉你序列9,8,5,。。。然而,代表-我们将:
9 : field 1, fixed 64-bit
8 5 26 5 24 238 98 32 <== payload for above
1 : field 0, fixed 64-bit
^^ not *really* valid, but fields <= 0 generally mean "stop" - but
frankly this is not a clean/defined/expected exit condition
这给了我们9
,我们还有9
字节,所以看起来不错
8 : Field 1, varint
5 = payload of above
26 : Field 3, length-delimited
5 = length of payload
24 238 98 32 1 = payload of ^^^
24 : Field 3, varint
238, 98 = payload of ^^^ = 12654
32 : Field 4, varint
1 = payload of ^^^ = 1
现在看起来它应该解析。。。调查为什么不是
编辑2:经过一点调试后,部分原因是您(很抱歉)损坏了v3ddeta
属性。您在proto中将它们定义为int32
(字段3是数据中的变量),但您将它们实现为double
。。。和double
和int32
不是朋友
因此:
然后,以下方法可以很好地工作:
using (var ms = new MemoryStream(buffer))
{
int len = ProtoReader.DirectReadVarintInt32(ms);
var resp = (Response)model.Deserialize(ms, null, typeof(Response), len);
Assert.AreEqual(5, resp.Type);
Assert.AreEqual(1, resp.v3dDelta.Count);
Assert.AreEqual(12654, resp.v3dDelta[0].ask);
Assert.AreEqual(1, resp.v3dDelta[0].askSize);
}
从技术上讲,我可以让protobuf net接受一个varint
值作为double
值,但这高度表明一个模式并不真正匹配,因此我认为正确的做法是在这种情况下更改类型。一切正常。。。真有趣!一切正常。。。真有趣!是的,就是它,现在它正常工作了。我只是忘记了在proto中更改字段类型之后更改字段类型。谢谢你,很抱歉耽误了你的时间。是的,就是这样,现在它正常工作了。我只是忘记了在proto中更改字段类型之后更改字段类型。谢谢你,很抱歉耽误了你的时间。