Le serveur TCP surveille et traite les connexions client entrantes sur un port déterminé. Dès qu'une connexion a été acceptée, il est possible de recevoir des données de la part des clients, et d'en envoyer vers un client spécifique ou vers tous les clients.
La bibliothèque fournit deux versions du bloc fonction FB_TCPServer. Le FB_TCPServer2 est une version améliorée qui prend en charge les connexions en utilisant TLS (Transport Layer Security).
La prise en charge ou non d'une connexion utilisant le protocole TLS dépend du contrôleur sur lequel FB_TcpServer2 est utilisé. Consultez le manuel spécifique de votre contrôleur pour vérifier si la communication TCP qui utilise TLS est prise en charge.
Le principe de fonctionnement des blocs fonction est le même. Il y a quelques différences pour les propriétés fournies et les méthodes qui sont décrites dans les chapitres respectifs.
La méthode Open ou OpenTls est généralement appelée en premier. Un numéro de port TCP et, éventuellement, l'adresse IP d'une interface sur laquelle surveiller sont indiqués. L'étape suivante consiste à récupérer la valeur de la propriété State, de façon cyclique, jusqu'à ce qu'elle soit différente de Opening. Si l'état ne passe pas à Opened, une erreur s'est produite. Vous pouvez alors déterminer la cause du problème d'après la valeur de la propriété Result.
Si l'opération aboutit (état = Opened), le serveur est prêt à accepter des connexions entrantes. Comme indiqué par la propriété IsNewConnectionAvailable. Elle doit être vérifiée de façon cyclique par l'application. Si sa valeur est TRUE, la méthode Accept doit être appelée. L'adresse IP et le port d'origine de la connexion sont alors renvoyés. À l'aide d'un programme, vous pouvez ensuite décider de maintenir ou non la connexion. La propriété NumberOfConnectedClients permet de vérifier le nombre de clients connectés.
Pour vérifier si un client a envoyé des données au serveur et si celles-ci peuvent être lues, utilisez la propriété IsDataAvailable. Avec les méthodes ReceiveFromFirstAvailableClient et PeekFromFirstAvailableClient, il est possible de lire les données sur le premier client où des données sont disponibles sans connaître son adresse IP ni son port. Tant que la méthode n'est pas appelée, l'application ne permet pas de savoir à partir de quel client les données sont lues. L'adresse IP et le port du client sont donc fournies comme sorties des méthodes. Sauf mention contraire dans la présente description, le principe de fonctionnement des méthodes FB_TCPServer/FB_TCPServer2 est identique à celui de FB_TCPClient/FB_TCPClient2 .
La méthode SendToSpecificClient peut être utilisée pour répondre directement à un client après réception des données via la méthode ReceiveFromFirstAvailableClient. Dans ce cas, l'application doit fournir l'adresse IP et le port d'un client connecté au serveur TCP. Le principe est ensuite le même qu'avec la méthode Send de FB_TCPClient/FB_TCPClient2.
Pour envoyer des données aux clients connectés, utilisez la méthode SendToAll. Avec la méthode SendToAll, une erreur du client met fin à la transmission vers ce dernier et le nombre d'octets envoyés est retourné. Par la suite, vous pouvez déterminer si tous les octets ont été envoyés à l'ensemble des clients en comparant la somme des octets envoyés et la quantité de données à envoyer multipliée par le nombre de clients.
Lorsque le serveur TCP est à l'état Listening, la méthode CheckClients doit être appelée de façon cyclique pour déterminer si un client a fermé la connexion. Il est aussi possible de récupérer la propriété NumberOfConnectedClients. En cas de déconnexion par un client et s'il n'y a plus aucune donnée à lire de cette connexion client, celle-ci est fermée et libérée pour permettre une nouvelle connexion entrante. Sinon, la connexion est maintenue disponible jusqu'à la lecture des données ou l'appel de la méthode DisconnectClient pour cette connexion. Lors de l'appel de la méthode DisconnectClient, les données reçues du client indiqué non encore traitées sont rejetées.
L'échec du traitement d'une méthode est indiqué dans la valeur de la propriété Result. La valeur de Result doit être vérifiée après chaque appel de méthode. La méthode ResetResult permet de réinitialiser le résultat sur Ok.
Le bloc fonction n'a ni entrées, ni sorties. Il remplit sa fonction par le biais de méthodes et de propriétés. Afin de détecter les déconnexions des clients connectés, la méthode CheckClients doit être appelée cycliquement. Vous pouvez aussi récupérer la propriété NumberOfConnectedClients. Vous pouvez vérifier que les clients sont encore connectés ou si la connexion a été fermée.
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;