.NET client
This sample project shows how a client for the PLC TCP/IP server can be realized under .NET4.0 in C#.

The sample uses the .NET libraries System.Net and System.Net.Sockets, with which a programmer can easily use socket functions. Pressing Enable causes the application to cyclically (depending on the value of TIMERTICK in [ms]) attempt to establish a connection to the server. If successful, a string with a maximum length of 255 characters can be sent to the server via the Send button. This string is then accepted by the server and sent back to the client. The connection is automatically closed on the server side after the SERVER_RECEIVE_TIMEOUT time defined in the server sample has expired, default: 50 seconds, if the server was unable to receive any new data from the client within this time.
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();
}
}
}
}