.NET-Client

In diesem Beispielprojekt wird gezeigt, wie unter .NET4.0 in C# ein Client für den SPS-TCP/IP-Server realisiert werden kann.

.NET-Client 1:

Das Beispiel nutzt die .NET-Bibliotheken System.Net und System.Net.Sockets, mit denen ein Programmierer ganz einfach Socket-Funktionen nutzen kann. Durch Drücken auf Enable versucht die Anwendung zyklisch (je nach dem Wert von TIMERTICK in [ms]) eine Verbindung zum Server herzustellen. Beim Erfolg kann ein String mit einer maximalen Länge von 255 Zeichen über den Send-Button zum Server gesendet werden. Dieser String wird dann vom Server angenommen und an den Client zurückgesendet. Die Verbindung wird serverseitig nach Ablauf der im Serverbeispiel definierten SERVER_RECEIVE_TIMEOUT -Zeit, default: 50 Sekunden, automatisch geschlossen, wenn der Server innerhalb dieser Zeit keine neue Daten vom Client empfangen konnte.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net; 
using System.Net.Sockets;

/* ########################################################################################## 
 * This sample TCP/IP client connects to a TCP/IP-Server, sends a message and waits for the 
 * response. It is being delivered together with our TCP-Sample, which implements an echo server 
 * in PLC. 
 * ########################################################################################## */namespace TcpIpServer_SampleClient
{
 publicpartialclassForm1 : Form
 {
    /* ##########################################################################################     
    * Constants     
    * ########################################################################################## */privateconstint RCVBUFFERSIZE = 256; // buffer size for receive bufferprivateconststring DEFAULTIP = "127.0.0.1";
    privateconststring DEFAULTPORT = "200";
    privateconstint TIMERTICK = 100;
 
    /* ##########################################################################################     
    * Global variables     
    * ########################################################################################## */privatestaticbool _isConnected; // signals whether socket connection is active or notprivatestaticSocket _socket; // object used for socket connection to TCP/IP-ServerprivatestaticIPEndPoint _ipAddress; // contains IP address as entered in text fieldprivatestaticbyte[] _rcvBuffer; // receive buffer used for receiving response from TCP/IP-Serverpublic Form1()
    {
     InitializeComponent();
    }
 
    privatevoid Form1_Load(object sender, EventArgs e)
    {
     _rcvBuffer = newbyte[RCVBUFFERSIZE];
 
     /* ##########################################################################################     
     * Prepare GUI     
     * ########################################################################################## */
     cmd_send.Enabled = false;
     cmd_enable.Enabled = true;
     cmd_disable.Enabled = false;
     rtb_rcvMsg.Enabled = false;
     rtb_sendMsg.Enabled = false;
     rtb_statMsg.Enabled = false;
     txt_host.Text = DEFAULTIP;
     txt_port.Text = DEFAULTPORT;
 
     timer1.Enabled = false;
     timer1.Interval = TIMERTICK;
     _isConnected = false;
    }
 
    privatevoid cmd_enable_Click(object sender, EventArgs e)
    {
     /* ##########################################################################################     
     * Parse IP address in text field, start background timer and prepare GUI     
     * ########################################################################################## */try
     {
        _ipAddress = newIPEndPoint(IPAddress.Parse(txt_host.Text), Convert.ToInt32(txt_port.Text));
        timer1.Enabled = true;
        cmd_enable.Enabled = false;
        cmd_disable.Enabled = true;
        rtb_sendMsg.Enabled = true;
        cmd_send.Enabled = true;
        txt_host.Enabled = false;
        txt_port.Enabled = false;
        rtb_sendMsg.Focus();
     }
     catch (Exception ex)
       {
        MessageBox.Show("Could not parse entered IP address. Please check spelling and retry. " + ex);
     }
    }
 
    /* ##########################################################################################     
    * Timer periodically checks for connection to TCP/IP-Server and reestablishes if not connected     
    * ########################################################################################## */privatevoid timer1_Tick(object sender, EventArgs e)
    {
     if (!_isConnected)
        connect();
    }
 
    privatevoid connect()
    {
     /* ##########################################################################################     
     * Connect to TCP/IP-Server using the IP address specified in the text field     
     * ########################################################################################## */try
     {
        _socket = newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
        _socket.Connect(_ipAddress);
        _isConnected = true;
        if (_socket.Connected)
         rtb_statMsg.AppendText(DateTime.Now.ToString() + ": Connectection to host established!\n");
        else
         rtb_statMsg.AppendText(DateTime.Now.ToString() + ": A connection to the host could not be established!\n");
     }
     catch (Exception ex)
     {
        MessageBox.Show("An error occured while establishing a connection to the server: " + ex);
     }
    }
 
    privatevoid cmd_send_Click(object sender, EventArgs e)
    {
     /* ##########################################################################################     
     * Read message from text field and prepare send buffer, which is a byte[] array. The last     
     * character in the buffer needs to be a termination character, so that the TCP/IP-Server knows     
     * when the TCP stream ends. In this case, the termination character is '0'.     
     * ########################################################################################## */ASCIIEncoding enc = newASCIIEncoding();
     byte[] tempBuffer = enc.GetBytes(rtb_sendMsg.Text);
     byte[] sendBuffer = newbyte[tempBuffer.Length + 1];
     for (int i = 0; i < tempBuffer.Length; i++)
        sendBuffer[i] = tempBuffer[i];
     sendBuffer[tempBuffer.Length] = 0;
 
     /* ##########################################################################################     
       * Send buffer content via TCP/IP connection     
     * ########################################################################################## */try
     {
        int send = _socket.Send(sendBuffer);
        if (send == 0)
         thrownewException();
        else
        {
         /* ##########################################################################################         
         * As the TCP/IP-Server returns a message, receive this message and store content in receive buffer.         
         * When message receive is complete, show the received message in text field.         
         * ########################################################################################## */
         rtb_statMsg.AppendText(DateTime.Now.ToString() + ": Message successfully sent!\n");
         IAsyncResult asynRes = _socket.BeginReceive(_rcvBuffer, 0, 256, SocketFlags.None, null, null);
         if (asynRes.AsyncWaitHandle.WaitOne())
         {
            int res = _socket.EndReceive(asynRes);
            char[] resChars = newchar[res + 1];
            Decoder d = Encoding.UTF8.GetDecoder();
            int charLength = d.GetChars(_rcvBuffer, 0, res, resChars, 0, true);
            String result = newString(resChars);
            rtb_rcvMsg.AppendText("\n" + DateTime.Now.ToString() + ": " + result);
            rtb_sendMsg.Clear();
         }
        }
     }
     catch (Exception ex)
       {
        MessageBox.Show("An error occured while sending the message: " + ex);
     }
    }
 
    privatevoid cmd_disable_Click(object sender, EventArgs e)
    {
     /* ##########################################################################################     
     * Disconnect from TCP/IP-Server, stop the timer and prepare GUI     
     * ########################################################################################## */
     timer1.Enabled = false;
     _socket.Disconnect(true);
     if (!_socket.Connected)
     {
        _isConnected = false;
        cmd_disable.Enabled = false;
        cmd_enable.Enabled = true;
        txt_host.Enabled = true;
        txt_port.Enabled = true;
        rtb_sendMsg.Enabled = false;
        cmd_send.Enabled = false;
        rtb_statMsg.AppendText(DateTime.Now.ToString() + ": Connectection to host closed!\n");
        rtb_rcvMsg.Clear();
        rtb_statMsg.Clear();
     }
    }
 }
}