NetworkStream class:阅读问题
NetworkStream class: Read Issue
我正在用核心 C#./NET 编写一个服务器客户端程序,我在其中将序列化的数据从一个客户端发送到服务器,但是当数据非常大时会发生两个异常。有时它工作正常但有时它只是抛出异常。
IOException
或抛出序列化异常。
这是接收和反序列化数据的代码:
MemoryStream mst = new MemoryStream();
strread.ReadTimeout = 250;
try
{
int b = strread.Read(outStream, 0, outStream.Length);
while (b > 0)
{
Console.WriteLine("Recieving Data " + b);
mst.Write(outStream, 0, b);
try
{
b = strread.Read(outStream, 0, outStream.Length);
}
catch (IOException ioEx)
{
Console.WriteLine(ioEx.TargetSite);
b = 0;
}
}
Console.WriteLine("Size of recieved bytes is " + b);
}
catch (Exception except)
{
Console.WriteLine(except.StackTrace + "\r\n" + except.TargetSite);
}
//int bcount = strread.Read(outStream, 0, outStream.Length);
mst.Read(outStream, 0, outStream.Length);
m = (Message)deserialize(outStream);
反序列化方法:
public Message deserialize(byte[] v)
{
IFormatter formatter = new BinaryFormatter();
MemoryStream mem = new MemoryStream();
Message mydat = null;
try
{
mem.Write(v, 0, v.Length);
mem.Seek(0, 0);
mydat = (Message)formatter.Deserialize(mem);
}
catch (SerializationException ex)
{
Console.WriteLine("Salman Deserialization " + ex.Message);
}
finally
{
mem.Flush();
mem.Close();
}
return mydat;
}
分析
目前Receiver似乎没有"message boundary"的概念。
Receiver 使用 MemoryStream
class 的实例累积接收到的数据,直到远程主机关闭连接:while (b > 0)
。所以,如果Sender发送了多条消息,然后Sender关闭了连接,Receiver完成接收累积,将两条消息都存储在MemoryStream
class的实例中。之后尝试对累积数据进行如下解释:
mst.Read(outStream, 0, outStream.Length);
m = (Message)deserialize(outStream);
这种解释可能存在的问题:
- 单条消息没有完全接收怎么办? — 反序列化失败。
- 如果收到多条消息怎么办? — 反序列化失败。
- 等等
解决方案
必须引入消息边界概念以从网络流(TCP 流)中提取("separate")消息。它可以通过使用固定大小的消息头或消息终止符来完成。
请参考文章:TCP/IP client-server application: exchange with string messages.
希望对您有所帮助!
我正在用核心 C#./NET 编写一个服务器客户端程序,我在其中将序列化的数据从一个客户端发送到服务器,但是当数据非常大时会发生两个异常。有时它工作正常但有时它只是抛出异常。
IOException
或抛出序列化异常。
这是接收和反序列化数据的代码:
MemoryStream mst = new MemoryStream();
strread.ReadTimeout = 250;
try
{
int b = strread.Read(outStream, 0, outStream.Length);
while (b > 0)
{
Console.WriteLine("Recieving Data " + b);
mst.Write(outStream, 0, b);
try
{
b = strread.Read(outStream, 0, outStream.Length);
}
catch (IOException ioEx)
{
Console.WriteLine(ioEx.TargetSite);
b = 0;
}
}
Console.WriteLine("Size of recieved bytes is " + b);
}
catch (Exception except)
{
Console.WriteLine(except.StackTrace + "\r\n" + except.TargetSite);
}
//int bcount = strread.Read(outStream, 0, outStream.Length);
mst.Read(outStream, 0, outStream.Length);
m = (Message)deserialize(outStream);
反序列化方法:
public Message deserialize(byte[] v)
{
IFormatter formatter = new BinaryFormatter();
MemoryStream mem = new MemoryStream();
Message mydat = null;
try
{
mem.Write(v, 0, v.Length);
mem.Seek(0, 0);
mydat = (Message)formatter.Deserialize(mem);
}
catch (SerializationException ex)
{
Console.WriteLine("Salman Deserialization " + ex.Message);
}
finally
{
mem.Flush();
mem.Close();
}
return mydat;
}
分析
目前Receiver似乎没有"message boundary"的概念。
Receiver 使用 MemoryStream
class 的实例累积接收到的数据,直到远程主机关闭连接:while (b > 0)
。所以,如果Sender发送了多条消息,然后Sender关闭了连接,Receiver完成接收累积,将两条消息都存储在MemoryStream
class的实例中。之后尝试对累积数据进行如下解释:
mst.Read(outStream, 0, outStream.Length);
m = (Message)deserialize(outStream);
这种解释可能存在的问题:
- 单条消息没有完全接收怎么办? — 反序列化失败。
- 如果收到多条消息怎么办? — 反序列化失败。
- 等等
解决方案
必须引入消息边界概念以从网络流(TCP 流)中提取("separate")消息。它可以通过使用固定大小的消息头或消息终止符来完成。
请参考文章:TCP/IP client-server application: exchange with string messages.
希望对您有所帮助!