Search code examples
c#xmltcp

XML Message over TCP in envelope


I have a task to replicate machinery interface into a system over TCP. The spec I have is as follows:

Field Value Size(bytes) Notes
Message Length + 2 2 Length in bytes of the XML message + 2, encoded as a two-byte, big-endian number
Message ID 8001 2 Message ID, encoded as a two-byte, big-endian number (Fixed Value).
Message The XML message itself, using UTF-8 character encoding.
EOF 0xff 1 End of the message envelope (fixed value)

I am comfortable building an app that can send the 'Message' portion to the endpoint (see below).

using System;
using System.Net.Sockets;
using System.Text;
using System.IO;

namespace ClientSocketApp
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                TcpClient client = new TcpClient("172.16.98.155", 12100);
                string messageToSend = "<message type=\"2635\" MSID=\"0\">\r\n<che CHID=\"MACHINE1\" action=\"L\" SPREAD=\"2\">\r\n<position PPOS=\"YARD\" JPOS=\"CTR\" QWGT=\"20000\"/>\r\n</che>\r\n</message>";
                byte[] sendData = Encoding.UTF8.GetBytes(messageToSend);

                NetworkStream stream = client.GetStream();
                stream.Write(sendData, 0, sendData.Length);

                Console.WriteLine("Sending data to server...");
                StreamReader sr = new StreamReader(stream);
                //string response = sr.ReadLine();
                //Console.WriteLine(response);

                stream.Close();

                //client.Close();
                Console.ReadKey();
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed to connect...");
            }
        }
    }
}

I am struggling to interpret the spec for length, ID and EOF if anyone has any bright ideas.


Solution

  • The spec are describing message framing. I.e. how the receiver know he has received the entire message and can deserialize the entire xml in one go. This mean the stream will contain a few binary values and a large string.

    Lets start by writing the xml message length. Presumably "a two-byte number" means a ushort, and lets create a helper method to deal with the big-endian conversion:

    private void WriteUshortBigEndian(Stream stream, int value){
      if(value> ushort.MaxValue) throw new Exception ...
      var bytes = BitConverter.GetBytes((ushort)value);
      if(BitConverter.IsLittleEndian){
          Array.Reverse( bytes );
      stream.Write(bytes , 0, 2 );
    }
    ...
    WriteUshortBigEndian(stream, sendData.Length);
    
    

    Next is the message id, this seem to be a fixed value of 8001

    WriteUshortBigEndian(stream, 8001);
    

    followed by the actual message:

    stream.Write(sendData, 0, sendData.Length);
    

    And finally a single 0xff byte

    strean.WriteByte((byte)0xff);