使用List作为protobuf中重复字段的对应部分是否正确?我试过这个并且总是例外:
无效的线型;这通常意味着您在不截断或设置长度的情况下覆盖了文件;见Using Protobuf-net, I suddenly got an exception about an unknown wire-type
整个缓冲区是(第一个msg,下一个到达的附加到此): 9 8 5 26 5 24 238 98 32 1
java protobuf文件:
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-net类:
[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 [],但结果是一样的。 阅读信息:
Response rsp = Serializer.DeserializeWithLengthPrefix<Response>(rcvstream, PrefixStyle.Base128);
并在java消息中使用writeDelimitedTo发送。 c#中的缓冲区与java中的缓冲区完全相同。 当有na v3dDelta字段时,一切都按预期工作。
答案 0 :(得分:1)
是的,List<T>
或数组(T[]
)适用于repeated
。顺便提一下,有一个工具可以从.proto定义生成protobuf-net类。
您试图以“长度前缀”读取它,但是:9 无效作为varint前缀( 9
,作为字段标题,表示“字段” 1,修复了64位数据“,但是:在这种情况下它应该是 varint )。
实际上,您的数据的无与9
兼容,因为您在定义中没有任何64位值作为字段1
。你做有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
再次:请检查您的数据。这看起来不像protobuf流,或者至少不是与你的模式匹配的。
编辑:可能java writeDelimitedTo包括只是长度,没有标题)使它在技术上不是一致的protobuf文件,但是...... meh),所以让我们调查:< / p>
int len = ProtoReader.DirectReadVarintInt32(ms);
给了我们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:经过一些调试之后,部分这是因为你(遗憾地说)borked V3DDelta
属性。您在proto中将它们定义为int32
(并且字段3是数据中的varint),但您将它们实现为double
... double
和int32
是不是朋友。
所以:
[ProtoContract]
public class V3DDelta
{
[ProtoMember(1)]
public int bid { get; set; }
[ProtoMember(2)]
public int bidSize { get; set; }
[ProtoMember(3)]
public int ask { get; set; }
[ProtoMember(4)]
public int askSize { get; set; }
}
然后以下工作正常:
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
值,但这高度表明模式不匹配,所以我认为在这种情况下改变类型是正确的。