FB_LocalServer
Here you can unpack the complete source for the server project: Example 1: Server;
The server must first be allocated a unique sLocalHost IP address and an nLocaPort IP port number. If the bEnable input is set, the local server will repeatedly try to open the listener socket once the PLCPRJ_RECONNECT_TIME has elapsed. The listener socket can usually be opened at the first attempt, if the TwinCAT TCP/IP Connection Server resides on the local PC. The functionality of a remote client was encapsulated in the function block FB_RemoteClient. The remote client instances are activated once the listener socket was opened successfully. Each instance of the FB_RemoteClient corresponds to a remote client, with which the local server can communicate simultaneously. The maximum number of remote clients communicating with the server can be modified via the value of the MAX_CLIENT_CONNECTIONS constant. In the event of an error, first all remote client connections are closed, followed by the listener sockets. The nAcceptedClients output provides information about the current number of connected clients.
Interface
FUNCTION_BLOCK FB_LocalServer
VAR_INPUT
sLocalHost : STRING(15) := '127.0.0.1';(* own IP address! *)
nLocalPort : UDINT := 0;
bEnable : BOOL;
END_VAR
VAR_OUTPUT
bListening : BOOL;
hListener : T_HSOCKET;
nAcceptedClients : UDINT;
bBusy : BOOL;
bError : BOOL;
nErrId : UDINT;
END_VAR
VAR
fbListen : FB_SocketListen := ( sSrvNetID := '', tTimeout := DEFAULT_ADS_TIMEOUT );
fbClose : FB_SocketClose := ( sSrvNetID := '', tTimeout := DEFAULT_ADS_TIMEOUT );
fbConnectTON : TON := ( PT := PLCPRJ_RECONNECT_TIME );
eStep : E_ServerSteps;
fbRemoteClient : ARRAY[1..MAX_CLIENT_CONNECTIONS ] OF FB_RemoteClient;
i : UDINT;
END_VAR
Implementation
CASE eStep OF
SERVER_STATE_IDLE:
IF bEnable XOR bListening THEN
bBusy := TRUE;
bError := FALSE;
nErrId := 0;
IF bEnable THEN
fbConnectTON( IN := FALSE );
eStep := SERVER_STATE_LISTENER_OPEN_START;
ELSE
eStep := SERVER_STATE_REMOTE_CLIENTS_CLOSE;
END_IF
ELSIF bListening THEN
eStep := SERVER_STATE_REMOTE_CLIENTS_COMM;
END_IF
SERVER_STATE_LISTENER_OPEN_START:
fbConnectTON( IN := TRUE, PT := PLCPRJ_RECONNECT_TIME );
IF fbConnectTON.Q THEN
fbConnectTON( IN := FALSE );
fbListen( bExecute := FALSE );
fbListen( sLocalHost:= sLocalHost,
nLocalPort:= nLocalPort,
bExecute := TRUE );
eStep := SERVER_STATE_LISTENER_OPEN_WAIT;
END_IF
SERVER_STATE_LISTENER_OPEN_WAIT:
fbListen( bExecute := FALSE );
IF NOT fbListen.bBusy THEN
IF NOT fbListen.bError THEN
bListening := TRUE;
hListener := fbListen.hListener;
eStep := SERVER_STATE_IDLE;
LogMessage( 'LISTENER socket OPENED!', hListener );
ELSE
LogError( 'FB_SocketListen', fbListen.nErrId );
nErrId := fbListen.nErrId;
eStep := SERVER_STATE_ERROR;
END_IF
END_IF
SERVER_STATE_REMOTE_CLIENTS_COMM:
eStep := SERVER_STATE_IDLE;
nAcceptedClients := 0;
FOR i:= 1 TO MAX_CLIENT_CONNECTIONS DO
fbRemoteClient[ i ]( hListener := hListener, bEnable := TRUE );
IF NOT fbRemoteClient[ i ].bBusy AND fbRemoteClient[ i ].bError THEN (*FB_SocketAccept returned error!*)
eStep := SERVER_STATE_REMOTE_CLIENTS_CLOSE;
EXIT;
END_IF
(* count the number of connected remote clients *)
IF fbRemoteClient[ i ].bAccepted THEN
nAcceptedClients := nAcceptedClients + 1;
END_IF
END_FOR
SERVER_STATE_REMOTE_CLIENTS_CLOSE:
nAcceptedClients := 0;
eStep := SERVER_STATE_LISTENER_CLOSE_START; (* close listener socket too *)
FOR i:= 1 TO MAX_CLIENT_CONNECTIONS DO
fbRemoteClient[ i ]( bEnable := FALSE );(* close all remote client (accepted) sockets *)
(* check if all remote client sockets are closed *)
IF fbRemoteClient[ i ].bAccepted THEN
eStep := SERVER_STATE_REMOTE_CLIENTS_CLOSE; (* stay here and close all remote clients first *)
nAcceptedClients := nAcceptedClients + 1;
END_IF
END_FOR
SERVER_STATE_LISTENER_CLOSE_START:
fbClose( bExecute := FALSE );
fbClose( hSocket := hListener,
bExecute:= TRUE );
eStep := SERVER_STATE_LISTENER_CLOSE_WAIT;
SERVER_STATE_LISTENER_CLOSE_WAIT:
fbClose( bExecute := FALSE );
IF NOT fbClose.bBusy THEN
LogMessage( 'LISTENER socket CLOSED!', hListener );
bListening := FALSE;
MEMSET( ADR(hListener), 0, SIZEOF(hListener));
IF fbClose.bError THEN
LogError( 'FB_SocketClose (listener)', fbClose.nErrId );
nErrId := fbClose.nErrId;
eStep := SERVER_STATE_ERROR;
ELSE
bBusy := FALSE;
bError := FALSE;
nErrId := 0;
eStep := SERVER_STATE_IDLE;
END_IF
END_IF
SERVER_STATE_ERROR:
bError := TRUE;
IF bListening THEN
eStep := SERVER_STATE_REMOTE_CLIENTS_CLOSE;
ELSE
bBusy := FALSE;
eStep := SERVER_STATE_IDLE;
END_IF
END_CASE