×
Menu
Index

TCP communication

 

Introduction

To communicate with the SoftRules® Service using TCP/IP an XML document or command has to be send to a specific TCP Port number at a specific IP address. This Port can be set using the Configuration Manager. This Port is coupled to a Configuration or the Configuration is specified in the request itself (TCP - DISPATCH Port).
 
The following functions are available using the server:
 
The descriptions of these functionalities are provided with programming examples in C#. Obviously the functionality SoftRules® is not limited to applications developed for the .Net framework.
 

Example

Here's an example in C# for sending an XML document to SoftRules® usin TCP/IP.
 
private string sendXml(string xml)
{
    const int READBUFSIZE = 8196;
    const int SENDBUFSIZE = 8196;
           
    TcpClient m_Client = null;
    Stopwatch m_TimeBetweenPackages = new Stopwatch();
 
    string m_IP = '127.0.0.1';
    string m_TCPPort = '56000';
    string m_ResultString = "";
 
    try
    {
        m_Client = new TcpClient(m_IP, m_TCPPort);
        m_Client.ReceiveBufferSize = READBUFSIZE;
        m_Client.SendBufferSize = SENDBUFSIZE;
 
        if (m_Client.Connected)
        {
            //write
 
            string signature = "SoftRules";
            byte[] signatureBytes = Encoding.UTF8.GetBytes(signature);
            byte[] requestBytes = Encoding.UTF8.GetBytes(xml);
            byte[] LengthBytes = BitConverter.GetBytes(requestBytes.Length);
 
            byte[] totalRequestBytes = new byte[signatureBytes.Length + LengthBytes.Length + requestBytes.Length];
 
            System.Buffer.BlockCopy(signatureBytes, 0, totalRequestBytes, 0, signatureBytes.Length);
            System.Buffer.BlockCopy(LengthBytes, 0, totalRequestBytes, signatureBytes.Length, LengthBytes.Length);
            System.Buffer.BlockCopy(requestBytes, 0, totalRequestBytes, signatureBytes.Length + LengthBytes.Length, requestBytes.Length);
 
            MemoryStream mStream = new MemoryStream(totalRequestBytes);
 
            byte[] sendBuffer = new byte[SENDBUFSIZE];
            int read = 0;
            while ((read = mStream.Read(sendBuffer, 0, sendBuffer.Length)) > 0)
            {
                m_Client.GetStream().Write(sendBuffer, 0, read);
            }
 
            //read
 
            byte[] rcvBuffer = new byte[READBUFSIZE];
            byte[] totalBuffer = new byte[0];
            int recvMsgSize = m_Client.GetStream().Read(rcvBuffer, 0, m_Client.ReceiveBufferSize);
 
            byte[] lengthBytes = new Byte[4];
 
            System.Buffer.BlockCopy(rcvBuffer, 0, signatureBytes, 0, 9);
            System.Buffer.BlockCopy(rcvBuffer, 9, lengthBytes, 0, 4);
            if (Encoding.UTF8.GetString(signatureBytes) == "SoftRules")
            {
                int lengthRequest = BitConverter.ToInt32(lengthBytes, 0);
                totalBuffer = new Byte[lengthRequest];
                int totalBytesReceived = recvMsgSize - 13;
                System.Buffer.BlockCopy(rcvBuffer, 13, totalBuffer, 0, recvMsgSize - 13);
 
                m_TimeBetweenPackages.Start(); //start stopwatch for max 5 sec.
                bool bStopReceiving = false;
 
                while ((totalBytesReceived < lengthRequest) && (!bStopReceiving))
                {
                    if (m_Client.Available > 0)
                    {
                        recvMsgSize = m_Client.GetStream().Read(rcvBuffer, 0, m_Client.ReceiveBufferSize);
 
                        System.Buffer.BlockCopy(rcvBuffer, 0, totalBuffer, totalBytesReceived, recvMsgSize);
                        totalBytesReceived += recvMsgSize;
                    }
 
                    if (m_TimeBetweenPackages.ElapsedMilliseconds > 5000)
                    {
                        bStopReceiving = true;
                    }
                }
 
                m_ResultString = Encoding.UTF8.GetString(totalBuffer);
            }                                       
        }
    }
    catch (SocketException se)
    {
        throw se;
    }
    catch (Exception e)
    {
        throw e;
    }
    finally
    {
        if (m_Client != null)
        {
            if (m_Client.Client != null)
            {
                m_Client.Client.Close();
            }
            m_Client.Close();
        }
    }
 
    return m_ResultString;
}
 

Response

The server returns an XML document following this schema (XSD):
 
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="softrulestcpframe">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="softrules" minOccurs="1" maxOccurs="1"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="softrules">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="header" minOccurs="1" maxOccurs="1"/>
                <xs:element ref="result" minOccurs="0" maxOccurs="1"/>
                <xs:element ref="xmldocument" minOccurs="0" maxOccurs="1"/>
                <xs:element ref="status" minOccurs="0" maxOccurs="1"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="result">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="errorcode"/>
                <xs:element ref="errordescription"/>
                <xs:element ref="errordetail"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="errorcode" type="xs:integer"/>
    <xs:element name="errordescription">
        <xs:complexType/>
    </xs:element>
    <xs:element name="errordetail">
        <xs:complexType/>
    </xs:element>
    <xs:element name="header">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="functionid" minOccurs="1" maxOccurs="1"/>
                <xs:element ref="configid" minOccurs="0" maxOccurs="1"/>
                <xs:element ref="inadapter" minOccurs="0" maxOccurs="1"/>
                <xs:element ref="outadapter" minOccurs="0" maxOccurs="1"/>
                <xs:element ref="parameters" minOccurs="0" maxOccurs="1"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="functionid" type="xs:integer"/>
    <xs:element name="configid" type="xs:integer"/>    <!-- Vereist bij een TCP Dispatch poort -->
    <xs:element name="inadapter" type="xs:string"/>    <!-- Vereist bij een TCP Dispatch poort -->
    <xs:element name="outadapter" type="xs:string"/>   <!-- Vereist bij een TCP Dispatch poort -->
    <xs:element name="parameters">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="parameter" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="parameter">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="name"/>
                <xs:element ref="value"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="name" type="xs:string"/>
    <xs:element name="value" type="xs:string"/>
    <xs:element name="xmldocument" type="xs:string"/> <!-- Dit is een CDATA section -->
    <xs:element name="status" type="xs:string"/>
</xs:schema>
 

Messages

Messages can be custom made and passed to the server (Raise Exception). The system will also generate its own messages, like validation messages. By default SoftRules® will use message code 1 if no messagecode is used.
 
Messagecode 2 is about validation messages on the Input XML.
Messagecode 3 is about validation message on the Output XML.
 
<softrulestcpframe>
     <softrules>
          <result>
               <configuration>O109 - Compleet bij Elkaar Pakket - Berekenen (1000)</configuration>
               <function>ProcessXml (14)</function>
               <messages>
                    <message>
                         <messagecode>2</messagecode>
                         <messagedescription>(1,422)  Het element PP_INGDAT is ongeldig. De waarde 23-09-2011 is ongeldig volgens het bijbehorende gegevenstype Decimal - De Pattern-beperking is mislukt.</messagedescription>
                         <Severity>Error</Severity>
                    </message>
                    <message>
                         <messagecode>2</messagecode>
                         <messagedescription>(1,216)  Het element PK_INGDAT is ongeldig. De waarde 23-09-2011 is ongeldig volgens het bijbehorende gegevenstype Decimal - De Pattern-beperking is mislukt.</messagedescription>
                         <Severity>Error</Severity>
                    </message>
                    <message>
                         <messagecode>3</messagecode>
                         <messagedescription>(1,7782)  Het element PP_TKRT is ongeldig. De waarde € 0,00 is ongeldig volgens het bijbehorende gegevenstype Decimal - De tekenreeks € 0,00 is geen geldige Decimal waarde.</messagedescription>
                         <Severity>Error</Severity>
                    </message>
               </messages>
          </result>
          <xmldocument/>
     </softrules>
</softrulestcpframe>