The TCP server monitors for and processes incoming client-connections on a specified port. After a connection has been accepted, data can be received from clients and data can be sent to one or to all clients.
The library provides two versions of the FB_TCPServer function block. The FB_TCPServer2 is an enhanced version which supports connections using TLS (Transport Layer Security).
Whether a connection using TLS is supported depends on the controller where the FB_TcpServer2 is used. Refer to the specific manual of your controller to verify if TCP communication using TLS is supported.
The working principle for both function blocks is the same. There are some differences for the provided properties and methods which are described in the respective chapters.
The usual order of commands is to call the Open or OpenTls method first, specifying a TCP port number and optionally an IP address of an interface to monitor on. Afterwards, retrieve the value of the State property cyclically until it is other than Opening. If the state does not transition to Opened, an error has occurred. Verify the value of the Result property to determine the reason.
When successful (State = Opened), the server is ready to accept incoming connections. It is indicated via the property IsNewConnectionAvailable. It must be verified periodically by the application and, in case the value is TRUE, the Accept method must be called. It returns the IP address and the port the connection is coming from. You can then programmatically determine whether to maintain the connection. The number of connected clients can be verified using the NumberOfConnectedClients property.
To verify whether a client has sent data to the server that is now available to read, use the property IsDataAvailable. The methods ReceiveFromFirstAvailableClient and PeekFromFirstAvailableClient can be used to read the data from the first client that has data available without having the IP and port of the client. Since it is undetermined by the application from which client the data is read from before calling the method, IP and port of the client are provided as outputs of the methods. Unless otherwise noted in the present description, the FB_TCPServer/FB_TCPServer2 methods operate as does the FB_TCPClient/FB_TCPClient2 .
The method SendToSpecificClient can be used to reply directly to a specific client after data has been received using the ReceiveFromFirstAvailableClient method. Therefore the application has to provide the IP address and port of a client connected to the TCP server. It then behaves like the Send method of FB_TCPClient/FB_TCPClient2.
To send data to the connected clients, use the SendToAll method. When using the SendToAll method, an error from the client terminates the transmission to that client, and the number of bytes sent is returned. Thereafter, you can determine whether the bytes have been sent to the clients by comparing the sum of the bytes sent with the amount of data to be sent multiplied by the number of clients.
While the state of the TCP server is Listening, the method CheckClients must be called cyclically to detect if a client has closed the connection. Alternatively, the property NumberOfConnectedClients can be retrieved. If a client-initiated disconnection has been detected and there is no more data to be read from that client connection, it is closed and made available for a new incoming connection. Otherwise, the connection is kept available until the data has been read or until the DisconnectClient method is called for that connection. When calling the method DisconnectClient, the data received from the specified client that has not yet been processed are discarded.
If processing in a method is unsuccessful, it is indicated in the value of the Result property. The value of Result must be verified after every method call. The result can be reset to Ok using the ResetResult method.
The function block does not have inputs and outputs. The functionality is available via methods and properties. In order to detect disconnections from connected clients, the method CheckClients must be called cyclically. Alternatively the value of the property NumberOfConnectedClients can be retrieved. Either can verify that clients are still connected or have closed the connection.
PROGRAM LibDocu_TcpServer2
VAR
xOpen : BOOL;
xOpenTls : BOOL;
xClose : BOOL;
etResult : TCPUDP.ET_Result;
etState : TCPUDP.ET_State;
iState : INT;
fbTcpServer : TCPUDP.FB_TCPServer2;
stTlsSettings : TCPUDP.ST_TlsSettingsServer;
sIp : STRING(15) := '';
uiPort : UINT := 12345;
END_VAR
CASE iState OF
0: // idle
IF xOpen OR xOpenTls THEN
IF xOpen AND_THEN NOT fbTcpServer.Open(sIp, uiPort) THEN
iState := 100; // error state
ELSIF xOpenTls AND_THEN NOT fbTcpServer.OpenTls(sIp, uiPort, stTlsSettings) THEN
iState := 100; // error state
END_IF
xOpen := xOpenTls := FALSE;
END_IF
IF fbTcpServer.State = TCPUDP.ET_State.Listening THEN
iState := 10;
END_IF
10: // listening
IF fbTcpServer.State = TCPUDP.ET_State.Idle THEN
iState := 0;
ELSIF fbTcpServer.State <> TCPUDP.ET_State.Listening AND fbTcpServer.State <> TCPUDP.ET_State.Closing THEN
iState := 100; // unexpected state
ELSIF fbtcpserver.IsNewConnectionAvailable THEN
fbTcpServer.Accept();
iState := 20; // state accepting
ELSE
IF xClose THEN
xClose := FALSE;
fbTcpServer.Close();
END_IF
(* your code comes here, e.g. check for data available to read *)
END_IF
20: // accepting
IF fbTcpServer.State <> TCPUDP.ET_State.Accepting AND fbTcpServer.State <> TCPUDP.ET_State.Listening THEN
iState := 100; // unexpected, go to error state
ELSIF fbTcpServer.State = TCPUDP.ET_State.Listening THEN
iState := 10;// incoming connection successful accepted
END_IF
100: // error state
(* your code comes here*)
END_CASE
etResult := fbTcpServer.Result;
etState := fbTcpServer.State;