El servidor TCP supervisa y procesa las conexiones de cliente entrantes en un puerto específico. Una vez aceptada una conexión, los datos se pueden recibir de los clientes y enviar a uno o todos los clientes.
La biblioteca incluye dos versiones del bloque de funciones FB_TCPServer. FB_TCPServer2 es una versión mejorada compatible con conexiones con TLS (Transport Layer Security, seguridad de la capa de transporte).
Que una conexión con TLS sea compatible o no dependerá del controlador en el que se utilice FB_TcpServer2. Consulte el manual específico del controlador para comprobar si es compatible la comunicación TCP con TLS.
El principio de funcionamiento para ambos bloques de funciones es idéntico. Existen ciertas diferencias para las propiedades y los métodos proporcionados. Estas se describirán en los capítulos correspondientes.
El orden habitual de los comandos es llamar primero el método Open o OpenTls, mediante la especificación de un número de puerto TCP y, opcionalmente, una dirección IP de una interfaz en la que supervisar. A continuación, recupere el valor de la propiedad State cíclicamente hasta que sea distinta a Opening. Si el estado no pasa a Opened, significa que se ha producido un error. Verifique el valor de la propiedad Result para determinar la razón.
Si es correcto (estado = Opened), el servidor está preparado para aceptar conexiones entrantes. Se indica a través de la propiedad IsNewConnectionAvailable. La aplicación debe verificarlo periódicamente y, si el valor es TRUE, se debe llamar el método Accept. Devuelve la dirección IP y el puerto de donde procede la conexión. Después, se puede determinar mediante programación si se va a mantener la conexión. El número de clientes conectados se puede comprobar mediante la propiedad NumberOfConnectedClients.
Para comprobar si un cliente ha enviado datos al servidor que ahora están disponibles para su lectura, utilice la propiedad IsDataAvailable. Los métodos ReceiveFromFirstAvailableClient y PeekFromFirstAvailableClient se pueden utilizar para leer los datos del primer cliente que tenga datos disponibles sin tener la IP ni el puerto del cliente. Puesto que la aplicación no puede determinar de qué cliente va a leer los datos antes de llamar el método, la IP y el puerto del cliente se proporcionan como salidas de los métodos. A menos que se indique lo contrario en esta descripción, los métodos FB_TCPServer/FB_TCPServer2 funcionan como FB_TCPClient/FB_TCPClient2 .
El método SendToSpecificClient se puede utilizar para responder directamente a un cliente específico después de recibir los datos mediante el método ReceiveFromFirstAvailableClient. Por lo tanto, la aplicación debe proporcionar la dirección IP y el puerto de un cliente conectado al servidor TCP. Entonces se comporta como el método Send de FB_TCPClient/FB_TCPClient2.
Para enviar datos a los clientes conectados, utilice el método SendToAll. Al utilizar el método SendToAll, un error del cliente finaliza la transmisión con dicho cliente, y se devuelve el número de bytes enviados. Por lo tanto, puede determinar si se han enviado los bytes a los clientes si compara la suma de los bytes enviados con la cantidad de datos que se van a enviar multiplicados por el número de clientes.
Mientras el estado del servidor TCP sea Listening, el método CheckClients se debe llamar cíclicamente para detectar si un cliente ha cerrado la conexión. De forma alternativa, se puede recuperar la propiedad NumberOfConnectedClients. Si se ha detectado una desconexión iniciada por un cliente y no hay más datos para leer en esa conexión de cliente, se cierra y pasa a estar disponible para una nueva conexión entrante. En caso contrario, la conexión se mantiene disponible hasta que los datos se hayan leído o hasta que se llame el método DisconnectClient para esa conexión. Cuando se llame el método DisconnectClient, los datos recibidos del cliente especificado que no se hayan procesado todavía se descartarán.
Si un proceso de un método no se realiza correctamente, se indica en el valor de la propiedad Result. El valor de Result se debe comprobar después de cada llamada de método. El resultado se puede restablecer a Ok mediante el método ResetResult.
El bloque de funciones no tiene entradas ni salidas. La funcionalidad está disponible a través de métodos y propiedades. Para poder detectar desconexiones de los clientes conectados, el método CheckClients deberá llamarse cíclicamente. Otra opción consiste en recuperar el valor de la propiedad NumberOfConnectedClients. Cualquiera de estas opciones comprueba si los clientes todavía están conectados o si han cerrado la conexión.
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;