Il server TCP rileva l'arrivo delle richieste di connessione client su una porta specifica e poi le elabora. Dopo che una connessione è stata accettata, i dati possono essere ricevuti dai client e possono essere inviati a uno o a tutti i client.
La libreria fornisce due versioni del blocco funzione FB_TCPServer. Il FB_TCPServer2 è una versione ottimizzata che supporta connessioni che utilizzano TLS (Transport Layer Security).
Il supporto di una connessione che utilizza TLS dipende dal controller dove si usa il FB_TcpServer2. Consultare il manuale specifico del controller per verificare se è supportata la comunicazione tramite TCP.
Il principio di funzionamento di entrambi i blocchi funzione è lo stesso. Vi sono alcune differenze per metodi e proprietà forniti descritti nei rispettivi capitoli.
Il normale ordine di comandi è quello di richiamare prima il metodo Open o OpenTls, specificando un numero di porta TCP e facoltativamente un indirizzo IP di un'interfaccia da monitorare. Successivamente, recuperare ciclicamente il valore della proprietà State fino a quando è diversa da Opening. Se lo stato non passa a Opened, si è verificato un errore. Verificare il valore della proprietà Result per determinare il motivo.
Quando l'operazione è corretta (Stato = Opened), il server è pronto ad accettare le connessioni in entrata. Questo è indicato tramite la proprietà IsNewConnectionAvailable. Deve essere verificato periodicamente dall'applicazione e, nel caso in cui il valore è TRUE, deve essere richiamato il metodo Accept. Il comando restituisce l'indirizzo IP e la porta da cui proviene la connessione. È possibile quindi determinare in modo programmatico se mantenere o meno la connessione. Il numero di client collegati si può verificare tramite la proprietà NumberOfConnectedClients.
Per verificare se il client ha inviato dati al server che ora è pronto alla lettura, usare la proprietà IsDataAvailable. Possono essere utilizzati i metodi ReceiveFromFirstAvailableClient e PeekFromFirstAvailableClient per leggere i dati dal primo client con dati disponibili senza disporre dell'IP e della porta del client. Poiché non è l'applicazione che determina da quale client i dati vengono letti prima di chiamare il metodo, l'IP e la porta del client sono utilizzati come uscite dei metodi. Se non diversamente indicato nella presente descrizione, i metodi del parametro FB_TCPServer/FB_TCPServer2 operano come FB_TCPClient/FB_TCPClient2 .
Il metodo SendToSpecificClient può essere utilizzato per rispondere direttamente a un client specifico dopo che i dati sono stati ricevuti utilizzando il metodo ReceiveFromFirstAvailableClient. Pertanto l'applicazione deve fornire l'indirizzo IP e la porta del client collegato al server TCP. Esso si comporta quindi come il metodo Send del parametro FB_TCPClient/FB_TCPClient2.
Per inviare i dati ai client collegati, utilizzare il metodo SendToAll. Quando si utilizza il metodo SendToAll, un errore proveniente dal client chiude la trasmissione a tale client e viene restituito il numero di byte inviati. In seguito, è possibile determinare se i byte sono stati inviati ai client confrontando la somma dei byte inviati con la quantità di dati da inviare moltiplicata per il numero di client.
Mentre lo stato del server TCP è Listening, deve essere richiamato ciclicamente il metodo CheckClients per rilevare se un client ha chiuso la connessione. Alternativamente può essere ripristinata la proprietà NumberOfConnectedClients. Se è stata rilevata una disattivazione della connessione da parte di un client, e non vi sono più dati da leggere dalla connessione di quel client, essa viene chiusa e resa disponibile per una nuova connessione in arrivo. In caso contrario, la connessione viene mantenuta disponibile fino alla lettura di tutti i dati o alla chiamata del metodo DisconnectClient per tale connessione. Quando si chiama il metodo DisconnectClient, i dati ricevuti dal client specificato che non sono ancora stati elaborati vengono eliminati.
Se l'elaborazione in un metodo non riesce, questo viene indicato nel valore della proprietà Result. Il valore di Result deve essere verificato dopo ogni chiamata di un metodo. Il risultato può essere reimpostato a Ok utilizzando il metodo ResetResult.
Il blocco funzione non ha ingressi e uscite. La funzionalità è disponibile attraverso i metodi e le proprietà. Per individuare disconnessioni dai client collegati, occorre chiamare ciclicamente il metodo CheckClients. In alternativa, è possibile recuperare il valore della proprietà NumberOfConnectedClients. Uno o l'altro possono verificare se i client sono ancora collegati oppure se hanno chiuso la connessione.
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;