Der TCP-Server überwacht einen angegebenen Port auf eingehende Client-Verbindungen und verarbeitet sie. Nachdem die Verbindung angenommen wurde, können Client-Daten empfangen und Daten an einen oder alle Clients gesendet werden.
Die Bibliothek stellt zwei Versionen des FB_TCPServer-Funktionsbausteins zur Verfügung. Der FB_TCPServer2 ist eine verbesserte Version, die Verbindungen über TLS (Transport Layer Security) unterstützt.
Ob eine Verbindung unter Verwendung TLS unterstützt wird, ist von der Steuerung abhängig, auf der der FB_TcpServer2 zum Einsatz kommt. Prüfen Sie im spezifischen Handbuch Ihrer Steuerung, ob Unterstützung für die TCP-Kommunikation mit TLS geboten wird.
Das Funktionsprinzip für die beiden Funktionsbausteine ist identisch. Es gibt einige Unterschiede bei den angegebenen Eigenschaften und Methoden, die in den jeweiligen Kapiteln erläutert werden.
Üblicherweise wird zunächst die Methode Open oder OpenTls aufgerufen, dabei werden eine TCP-Port-Nummer sowie ggf. die IP-Adresse der zu überwachenden Schnittstelle angegeben. Anschließend wird der Wert der Eigenschaft State solange zyklisch abgerufen, bis er von Opening abweicht. Wenn sich der Status nicht in Opened ändert, ist ein Fehler aufgetreten. Prüfen Sie den Wert der Eigenschaft Result, um den Grund dafür zu ermitteln.
Bei erfolgreicher Ausführung (Status = Opened) ist der Server bereit, eingehende Verbindungen anzunehmen. Dies ist an der Eigenschaft IsNewConnectionAvailable erkennbar. Sie muss regelmäßig von der Anwendung überprüft werden. Lautet der Wert TRUE, muss die Methode Accept aufgerufen werden. Sie gibt die IP-Adresse und den Port zurück, von dem die Verbindung stammt. Sie können nun programmseitig festlegen, ob die Verbindung beibehalten werden soll. Die Anzahl an verbundenen Clients ist aus der Eigenschaft NumberOfConnectedClients ersichtlich.
Die Eigenschaft IsDataAvailable gibt an, ob vom Client an den Server gesendete Daten vorliegen, die gelesen werden können. Mithilfe der Methoden ReceiveFromFirstAvailableClient und PeekFromFirstAvailableClient können die Daten vom ersten Client gelesen werden, auf dem Daten verfügbar sind, ohne dass die IP-Adresse oder die Portnummer des Clients vorliegen. Da vor dem Aufrufen der Methode nicht festgelegt wurde, wessen Daten gelesen werden sollen, werden die IP-Adresse und der Port des Clients als Methodenausgang geliefert. Sofern in dieser Beschreibung nicht anders angegeben, sind die Methoden FB_TCPServer/FB_TCPServer2 und FB_TCPClient/FB_TCPClient2 gleich.
Mit der Methode SendToSpecificClient kann einem bestimmten Client nach dem Empfang seiner Daten über die Methode ReceiveFromFirstAvailableClient direkt geantwortet werden. Die Anwendung muss dem TCP-Server daher die IP-Adresse und den Port des verbundenen Clients liefern. Anschließend verhält sie sich wie die Methode Send unter FB_TCPClient/FB_TCPClient2.
Um Daten an die verbundenen Clients zu senden, verwenden Sie die Methode SendToAll. Bei der Methode SendToAll wird die Übertragung an einen Client beendet, wenn bei diesem Client ein Fehler auftritt, und die Anzahl der gesendeten Bytes wird zurückgegeben. Durch Vergleichen der Summe der gesendeten Bytes mit der zu sendenden Datenmenge multipliziert mit der Anzahl der Clients kann ermittelt werden, ob alle Bytes an alle Clients gesendet wurden.
Wenn der TCP-Server den Status Listening aufweist, muss die Methode CheckClients zyklisch aufgerufen werden, um zu ermitteln, ob ein Client die Verbindung geschlossen hat. Alternativ kann auch die Eigenschaft NumberOfConnectedClients aufgerufen werden. Wenn eine vom Client initiierte Trennung erkannt wird und keine, aus dieser Client-Verbindung stammenden Daten mehr gelesen werden müssen, wird sie geschlossen und einer neuen eingehenden Verbindung bereitgestellt. Andernfalls bleibt die Verbindung verfügbar, bis die Daten gelesen wurden oder bis die Methode DisconnectClient für diese Verbindung aufgerufen wird. Wenn die Methode DisconnectClient aufgerufen wird, werden die Daten von dem angegebenen Client, die noch nicht verarbeitet wurden, verworfen.
Ist die Verarbeitung durch eine Methode nicht erfolgreich verlaufen, wird dies durch den Wert der Eigenschaft Result angegeben. Der Wert von Result muss nach jedem Methodenaufruf geprüft werden. Das Ergebnis kann auf Ok zurückgesetzt werden. Dazu dient die Methode ResetResult.
Der Funktionsbaustein weist keine Eingänge und Ausgänge auf. Die Funktionalität ist über Methode und Eigenschaften verfügbar. Um getrennte Clients zu erkennen, muss die Methode CheckClients zyklisch aufgerufen werden. Alternativ kann auch der Wert der Eigenschaft NumberOfConnectedClients aufgerufen werden. Mit beidem kann geprüft werden, ob die Clients weiterhin verbunden sind oder die Verbindung getrennt haben.
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;