FB_RemoteClient
If the bEnable input is set, an attempt is made to accept the connection request of a remote client, once the PLCPRJ_ACCEPT_POOLING_TIME has elapsed. The data exchange with the remote client was encapsulated in a separate function block (FB_ServerDataExcha). Once the connection was established successfully, the instance is activated via the FB_ServerDataExcha function block. In the event of an error, the accepted connection is closed, and a new connection is established.
Interface
FUNCTION_BLOCK FB_RemoteClient
VAR_INPUT
hListener : T_HSOCKET;
bEnable : BOOL;
END_VAR
VAR_OUTPUT
bAccepted : BOOL;
hSocket : T_HSOCKET;
bBusy : BOOL;
bError : BOOL;
nErrID : UDINT;
sFromClient : T_MaxString;
END_VAR
VAR
fbAccept : FB_SocketAccept := ( sSrvNetID := '', tTimeout := DEFAULT_ADS_TIMEOUT );
fbClose : FB_SocketClose := ( sSrvNetID := '', tTimeout := DEFAULT_ADS_TIMEOUT );
fbServerDataExcha : FB_ServerDataExcha;
fbAcceptTON : TON := ( PT := PLCPRJ_ACCEPT_POLLING_TIME );
eStep : E_ClientSteps;
END_VAR
Implementation
CASE eStep OF
CLIENT_STATE_IDLE:
IF bEnable XOR bAccepted THEN
bBusy := TRUE;
bError := FALSE;
nErrId := 0;
sFromClient := '';
IF bEnable THEN
fbAcceptTON( IN := FALSE );
eStep := CLIENT_STATE_CONNECT_START;
ELSE
eStep := CLIENT_STATE_CLOSE_START;
END_IF
ELSIF bAccepted THEN
eStep := CLIENT_STATE_DATAEXCHA_START;
ELSE
bBusy := FALSE;
END_IF
CLIENT_STATE_CONNECT_START:
fbAcceptTON( IN := TRUE, PT := PLCPRJ_ACCEPT_POLLING_TIME );
IF fbAcceptTON.Q THEN
fbAcceptTON( IN := FALSE );
fbAccept( bExecute := FALSE );
fbAccept( hListener := hListener,
bExecute:= TRUE );
eStep := CLIENT_STATE_CONNECT_WAIT;
END_IF
CLIENT_STATE_CONNECT_WAIT:
fbAccept( bExecute := FALSE );
IF NOT fbAccept.bBusy THEN
IF NOT fbAccept.bError THEN
IF fbAccept.bAccepted THEN
bAccepted := TRUE;
hSocket := fbAccept.hSocket;
LogMessage( 'REMOTE client ACCEPTED!', hSocket );
END_IF
eStep := CLIENT_STATE_IDLE;
ELSE
LogError( 'FB_SocketAccept', fbAccept.nErrId );
nErrId := fbAccept.nErrId;
eStep := CLIENT_STATE_ERROR;
END_IF
END_IF
CLIENT_STATE_DATAEXCHA_START:
fbServerDataExcha( bExecute := FALSE );
fbServerDataExcha( hSocket := hSocket,
bExecute := TRUE );
eStep := CLIENT_STATE_DATAEXCHA_WAIT;
CLIENT_STATE_DATAEXCHA_WAIT:
fbServerDataExcha( bExecute := FALSE, sFromClient=>sFromClient );
IF NOT fbServerDataExcha.bBusy THEN
IF NOT fbServerDataExcha.bError THEN
eStep := CLIENT_STATE_IDLE;
ELSE
(* possible errors are logged inside of fbServerDataExcha function block *)
nErrId := fbServerDataExcha.nErrID;
eStep := CLIENT_STATE_ERROR;
END_IF
END_IF
CLIENT_STATE_CLOSE_START:
fbClose( bExecute := FALSE );
fbClose( hSocket:= hSocket,
bExecute:= TRUE );
eStep := CLIENT_STATE_CLOSE_WAIT;
CLIENT_STATE_CLOSE_WAIT:
fbClose( bExecute := FALSE );
IF NOT fbClose.bBusy THEN
LogMessage( 'REMOTE client CLOSED!', hSocket );
bAccepted := FALSE;
MEMSET( ADR( hSocket ), 0, SIZEOF( hSocket ) );
IF fbClose.bError THEN
LogError( 'FB_SocketClose (remote client)', fbClose.nErrId );
nErrId := fbClose.nErrId;
eStep := CLIENT_STATE_ERROR;
ELSE
bBusy := FALSE;
bError := FALSE;
nErrId := 0;
eStep := CLIENT_STATE_IDLE;
END_IF
END_IF
CLIENT_STATE_ERROR:
bError := TRUE;
IF bAccepted THEN
eStep := CLIENT_STATE_CLOSE_START;
ELSE
eStep := CLIENT_STATE_IDLE;
bBusy := FALSE;
END_IF
END_CASE