C# 有没有办法标记每个protobuf网络记录的结束

C# 有没有办法标记每个protobuf网络记录的结束,c#,protobuf-net,C#,Protobuf Net,我正在将一系列protobuf net对象保存在数据库单元格中,作为长度前缀为protobuf net对象的字节[]: //retrieve existing protobufs from database and convert to Byte[] object q = sql_agent_cmd.ExecuteScalar(); older-pbfs = (Byte[])q; // serialize the new pbf to add into MemoryStream m //now

我正在将一系列protobuf net对象保存在数据库单元格中,作为长度前缀为protobuf net对象的字节[]:

//retrieve existing protobufs from database and convert to Byte[]
object q = sql_agent_cmd.ExecuteScalar();
older-pbfs = (Byte[])q;

// serialize the new pbf to add into MemoryStream m
//now write p and the new pbf-net Byte[] into a memory stream and retrieve the sum

var s = new System.IO.MemoryStream();
s.Write(older-pbfs, 0, older-pbfs.Length);
s.Write(m.GetBuffer(), 0, m.ToArray().Length); // append new bytes at the end of old
Byte[] sum-pbfs = s.ToArray();

//sum-pbfs = old pbfs + new pbf. Insert sum-pbfs into database
这个很好用。我关心的是如果数据库有轻微的损坏会发生什么。不再可能知道哪个字节是长度前缀,整个单元格内容都将被丢弃。是否建议也使用某种pbf结束对象指示符(类似于文本文件中使用的\n或EOF指示符)。这样,即使一条记录损坏,其他记录也可以恢复

如果是,建议在每个pbf末尾添加记录结束指示器的方法是什么

在VisualStudio2010上使用protobuf-netv2和C#

谢谢 Manish

(注意:我不太了解protobuf网络本身,但这通常适用于协议缓冲区消息。)

通常,如果您想要记录多条消息,只需放置一条“包装器”消息就值得了——将“真实”消息作为其中的重复字段。然后,每个“真实”消息将以协议缓冲区的自然有线格式作为长度前缀


当然,这不会检测到损坏-但老实说,如果数据库最终损坏,您将面临更大的问题。您可能会检测到损坏,例如,通过在每个记录中保留一个哈希。。。但是,您需要考虑在长度前缀或散列本身内发生的损坏的可能性。想一想你在这里真正想要实现的是什么——你想要保护什么场景,需要什么级别的恢复。

如果你通过
序列化
/
反序列化
使用普通消息,那么否:这不是规范的一部分(因为格式设计为可附加的)

但是,如果您使用
SerializeWithLengthPrefix
,它将转储消息开头的长度;然后它将提前知道需要多少数据。您使用
反序列化WithLengthPrefix
,如果没有足够的数据,它会大声抱怨。然而!如果您有额外的数据,它不会抱怨,因为这也是可附加的

就Jon的回复而言,
*WithLengthPrefix
方法的默认用法是存储的数据与Jon建议的完全相同;它假装存在一个包装器对象,并相应地进行操作。区别在于:

  • 实际上不存在包装器对象
  • “withlengthprefix”方法在一次出现后显式停止,而不是将任何后续数据合并到同一对象中(例如,用于将多个离散对象发送到单个文件或单个套接字)
这里两个“可追加”的不同之处在于,第一个表示“合并为单个对象”,而第二个表示“我希望有多个记录”

无关建议:

s.Write(m.GetBuffer(), 0, m.ToArray().Length);
应该是:

s.Write(m.GetBuffer(), 0, (int)m.Length);

(无需创建额外缓冲)

非常感谢您的反馈。我终于找到了一种方法,看看protobuf网络是否允许重复字段。看来并非如此。我可以看到字段的IsRepeated=True选项,但不能看到IsRepeated=True。@Manish:它肯定会处理重复的字段。我希望它们能被模拟成收藏品。非常感谢。一个相关的问题。序列化程序是否有可用于通过网络发送字节[]和PBF的方法。标准机制似乎是通过字节[]循环,直到到达末尾。但是像Serializer.send(clientStream,sum-pbfs)这样的东西会很棒。@Manish我不理解这个问题;什么是“总PBF”?如果使用WithLengthPrefix方法,它不会读取一条消息。您还可以创建一个固定长度的ProtoReader IIRC,并使用它——或者可能有一个接受固定长度的反序列化重载(不记得了,但肯定很容易在公共API上完成)。我为不够清晰而道歉。sum pbfs在上面的代码段中,它本质上是序列化pbfs的字节[]。所有通过套接字发送字节[]的示例都表明,我们一次遍历它2kb。我希望有一种更简单的方式来传输字节[]。但是在你的评论之后,我想我还是会一次发送一个pbf。谢谢