FB_LocalServer

Dem Server muss zuerst eine eindeutige sLocalHost-IP Adresse und eine nLocaPort-IP Portnummer zugewiesen werden. Beim gesetzten bEnable-Eingang versucht der Local-Server immer wieder nach Ablauf der SERVER_RECONNECT_TIME den Listener-Socket zu öffnen. Im Regelfall kann der Listener-Socket beim ersten Versuch geöffnet werden, wenn sich der TwinCAT TCP/IP Connection Server auf dem lokalen PC befindet. Die Funktionalität eines Remote-Clients wurde in dem Funktionsbaustein FB_RemoteClient gekapselt. Die Instanzen der Remote-Clients werden aktiviert, nachdem der Listener-Socket geöffnet werden konnte. Jede Instanz vom FB_RemoteClient entspricht einem Remote-Client mit dem der Local-Server gleichzeitig kommunizieren kann. Die maximale Anzahl der mit dem Server kommunizierenden Remote-Clients kann durch den Wert der MAX_CLIENT_CONNECTIONS-Konstanten verändert werden. Bei einem Fehler werden zuerst alle Remote-Client-Verbindungen und dann der Listener-Sockets geschlossen. Der nAcceptedClients‑Ausgang gibt Auskunft über die aktuelle Anzahl der verbundenen Clients.
Schnittstelle
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
Realisierung
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