NetworkStream class: Read Issue

88 views Asked by At

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. Sometimes it works fine but sometimes it just throws exception. IOException or Serialisation Exception is thrown.

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

There are 1 answers

0
Sergey Vyacheslavovich Brunov On BEST ANSWER

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

Hope this helps!