我使用BinaryFormatter通过NetworkStream序列化对象 像这样的代码
//OpenConnection ...
TCPClient client = server.AcceptTCPConnection();
Message message = new Message("bla bla"); // This is the serializable class
NetworkStream stream = client.GetStream(); // Get Stream
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(stream, message);
stream.Flush();
stream.Close(); //Close Connection
在客户端代码中,我们只需要从流中读取
bf.Deserialize(stream) as Message
获取我们刚从Server发送的对象。
但是这里有一个问题,如果我删除了行stream.Close();
,则客户端无法读取此对象。或者我可以更改为stream.Dispose();
但是,我想再次使用此流来发送另一个Message
,我该怎么办?请帮助,这让我感到头疼@@
更新 我找到了这个问题的原因。因为我使用一台机器来运行客户端和服务器。它绝对适用于两台不同的机器。有人可以告诉我为什么?几天前就遇到了大问题。
答案 0 :(得分:3)
发送多个单独的消息涉及“成帧” - 将单个通道拆分为单独的块,这些块不需要客户端“读取结束”。但奇怪的是,我的印象是BinaryFormatter
已经实施了基本框架 - 但是:我可能错了。在一般情况下,使用二进制协议时,最常见的方法是在每条消息前面加上有效负载的长度,即
using(var ms = new MemoryStream()) {
while(...)
{
// not shown: serialize to ms
var len BitConverter.GetBytes((int)ms.Length);
output.Write(len, 0, 4);
output.Write(ms.GetBuffer(), 0, (int) ms.Length);
ms.SetLength(0); // ready for next cycle
}
}
来电者必须:
如果这听起来像是很多工作,也许只需使用一个为你完成所有这些工作的序列化工具;例如,使用protobuf-net,这将是:
while(...) { // each item
Serializer.SerializeWithLengthPrefix(output, PrefixStyle.Base128, 1);
}
读者将是:
foreach(var msg in Serializer.DeserializeItems<Message>(
input, PrefixStyle.Base128, 1))
{
// ...
}
(注意:这不使用与BinaryFormatter
相同的格式/规则)