简体   繁体   English

NetworkStream类:读取问题

[英]NetworkStream class: Read Issue

I am making a Server client program in core C#./NET in which I send the data that is serialised from one client to server but there are two exceptions that occur when data is very large. 我正在核心C#。/ NET中制作一个Server客户端程序,在该程序中,我将从一个客户端序列化的数据发送到服务器,但是当数据非常大时会发生两种异常。 Sometimes it works fine but sometimes it just throws exception. 有时它工作正常,但有时它会引发异常。 IOException or Serialisation Exception is thrown. 引发IOException或序列化异常。

Here is the code to receive and deserialise the data: 这是接收和反序列化数据的代码:

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);

Deserialization method: 反序列化方法:

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;
}

Analysis 分析

It seems currently the Receiver does not have the notion of the "message boundary". 目前看来,接收方没有“消息边界”的概念。

The Receiver accumulates the received data using the instance of the MemoryStream class until the remote host shuts down the connection: while (b > 0) . Receiver使用MemoryStream类的实例累积接收到的数据,直到远程主机关闭连接: while (b > 0) So, if multiple messages are sent by the Sender and after that the connection is closed by Sender, the Receiver completes the receiving accumulation having both messages stored in the instance of the MemoryStream class. 因此,如果发件人发送了多个消息,然后发件人关闭了连接,则接收方将完成接收累积,将两条消息都存储在MemoryStream类的实例中。 After that there is an attempt to interpret the accumulated data as follows: 之后,尝试如下解释累积的数据:

mst.Read(outStream, 0, outStream.Length);
m = (Message)deserialize(outStream);

Possible problems with such interpretation: 此类解释可能存在的问题:

  • What if the single message has not been completely received? 如果未完全收到单个消息怎么办? — Failed to deserialize. —无法反序列化。
  • What if multiple messages have been received? 如果收到多条消息怎么办? — Failed to deserialize. —无法反序列化。
  • etc. 等等

Solution

The message boundary concept must be introduced to extract ("separate") the messages from the network stream (TCP-stream). 必须引入消息边界概念以从网络流(TCP流)中提取(“分离”)消息。 It can be done either by using the fixed-size message header or the message terminator. 可以通过使用固定大小的消息头或消息终止符来完成。

Please refer to the article: TCP/IP client-server application: exchange with string messages . 请参阅文章: TCP / IP客户端-服务器应用程序:与字符串消息交换

Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM