我在how to send large objects over TCP发布了一个问题,似乎主要问题已经解决,但现在经常我得到另一个例外:
二进制流'0'不包含 有效的BinaryHeader。可能的原因 是无效的流或对象版本 序列化和。之间的变化 反序列化。
问题仍在我的接收方法中:
public Message Receive()
{
if (_tcpClient == null || !_tcpClient.Connected)
{
throw new TransportException("Client Not Connected");
}
// buffers
byte[] msgBuffer;
byte[] sizeBuffer = new byte[sizeof(int)];
// bites read
int readSize = 0;
// message size
int size = 0;
MemoryStream memStream = new MemoryStream();
NetworkStream netStream = _tcpClient.GetStream();
BinaryFormatter formatter = new BinaryFormatter();
try
{
// Read the message length
netStream.Read(sizeBuffer, 0, sizeof(int));
// Extract the message length
size = BitConverter.ToInt32(sizeBuffer, 0);
msgBuffer = new byte[size];
// Fill up the message msgBuffer
do
{
// Clear the buffer
Array.Clear(msgBuffer, 0, size);
// Read the message
readSize += netStream.Read(msgBuffer, 0, _tcpClient.ReceiveBufferSize);
// Write the msgBuffer to the memory streamvb
memStream.Write(msgBuffer, 0, readSize);
} while (readSize < size);
// Reset the memory stream position
memStream.Position = 0;
// Deserialize the message
return (Message)formatter.Deserialize(memStream); // <-- Exception here
}
catch (System.Exception e)
{
if (_tcpClient == null || !_tcpClient.Connected)
{
throw new TransportException("Client Not Connected");
}
else
{
throw e;
}
}
}
可以在我的original question中找到与此示例相关的其余代码。
有人知道造成这种异常的原因以及如何避免它吗?
将Read
更改为一次读取最多_tcpClient.ReceiveBufferSize
个字节,而不是尝试读取完整的邮件大小(可能大于缓冲区大小)以及例外情况略有下降,但仍然经常发生。
答案 0 :(得分:3)
让我建议您稍微简化一下代码:
public Message Receive()
{
try
{
if (_tcpClient == null || !_tcpClient.Connected)
{
throw new TransportException("Client Not Connected");
}
using (var stream = _tcpClient.GetStream())
using (var reader = new BinaryReader(stream))
{
int size = reader.ReadInt32();
byte[] buffer = reader.ReadBytes(size);
using (var memStream = new MemoryStream(buffer))
{
var formatter = new BinaryFormatter();
return (Message)formatter.Deserialize(memStream);
}
}
}
catch (System.Exception e)
{
if (_tcpClient == null || !_tcpClient.Connected)
{
throw new TransportException("Client Not Connected");
}
throw e;
}
}
另外,如果你这样做是为了娱乐和/或教育目的,那么没关系,但在一个真实的项目中你应该考虑WCF,以便通过网络传输对象。
答案 1 :(得分:0)
WCF在客户端 - 服务器上不太好。轮询双工是一项非常原始的技术。