-1

Currently, I'm receiving data whenever it is 17 bytes. However, I have two types of data, 17 bytes and 10 bytes. How can I make it process when I have two types of data?

        byte[] message = new byte[17];
        int bytesRead;

        while (true)
        {
            bytesRead = 0;

            try
            {
                //blocks until a client sends a message
                bytesRead = clientStream.Read(message, 0, 17);

            }
            catch
            {
                //a socket error has occured
                break;
            }

            if (bytesRead == 0)
            {
                //the client has disconnected from the server
                break;
            }

I have seen similar questions asked but it's in C and I couldn't understand. Kindly assist me.

Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
active92
  • 644
  • 12
  • 24
  • 1
    You need an application protocol to provide in message framing. You're now assuming you receive a 17-byte message, but you could very well be reading a 10-byte message and the first 7 bytes of the next message. We cannot answer this for you. – CodeCaster Jun 15 '16 at 10:25
  • 1
    You can let your datatypes be 18 and 11 bytes. The first byte will be the identificator. You read one byte, test it for your message type to know if you have to read 10 or 17 bytes. Then you read your databytes. – Holger Jun 15 '16 at 10:31
  • @CodeCaster Thank you. Will try your suggestion. – active92 Jun 15 '16 at 10:31
  • 1
    I have some answers about message framing: [Message framing (start reading from the 4th paragraph)](http://stackoverflow.com/a/36345290/3740093) --- [Message framing example](http://stackoverflow.com/a/35240061/3740093). – Visual Vincent Jun 15 '16 at 10:49

1 Answers1

2

You are trying to implement a message exchange on top of a stream-based protocol (like TCP). When the messages have different lengths and/or types, there are two common approaches

  • framed messages: Each message will consist of a header of known length that contains the message's length and type and possibly other metadata (e.g. a timestamp). After reading the header, the appropriate amount of bytes (i.e. the payload) is read from the stream.
  • self-delimiting messages: The end of a message can be detected by the content of the stream read so far. One example for self-delimiting is the HTTP Header, which is delimited by a double newline (2x CRLF).

IMHO framed messaging is easier to implement since you always know how many bytes to read. For self-delimiting messages you have to employ buffering and parsing to detect the end of the message. Furthermore you have to make sure that the end-of-message-marker does not appear in the message's payload.

To implement the receiving side of a framed messaging protocol you can use the System.IO.BinaryReader class.

  • read the length of the message using ReadByte() or one of the ReadUInt*() methods if the messages will become longer than 255 bytes
  • read the payload using Read(Byte[], Int32, Int32). Please note that Read may return even if less bytes than specified have been read. You have to use a loop to fill byte[] message.
code_onkel
  • 2,759
  • 1
  • 16
  • 31
  • thanks a lot for your detailed explanation. i've decided to implement framed messages as it is much more convenient in my case. – active92 Jun 16 '16 at 00:40