SERVIDOR TCP/IP - FUNCIONES PAWN DISPONIBLES
Actualmente el servidor soporta hasta (2) dos conexiones simultáneamente.
Si se excede ese valor, las conexiones nuevas serán rechazadas hasta que esté libre alguna.
La constante TCPSERV_MAX_CONNECTIONS contiene el número máximo de conexiones simultáneas,
así como la función TcpServerGetMaxId() que retorna el mismo valor.
Cada conexión aceptada por el servidor, se transforma en una conexión activa que se identifica con un "Id",
que es un numero positivo y mayor a cero. El valor del "Id" debe usarse para leer o enviar datos por una
conexión determinada, o para cualquier operación donde deba aplicarse a una conexión en particular.
Luego crearemos la nota de aplicación propiamente dicha con la documentación para el servidor, pero mientras tanto,
esta son las funciones disponibles.
TcpServerInit(ServerPort=48000, TimeoutIdle=10)
Inicializa y activa el servidor TCP/IP.
ENTRADAS:
- ServerPort = Puerto TCP donde escucha conexiones el servidor.
- TimeoutIdle = Segundos de timeout-idle antes de desconectar a un cliente por inactividad. Máximo 125 segundos.
RETORNO:
- ( 0 ) = Operación exitosa.
- ( -1 ) = Error, El servidor ya se encuentra inicializado.
- ( -2 ) = Error, falla de inicialización, error de memoria.
- ( -10 ) = Error, puerto TCP invalido.
EJEMPLO:
// Inicializar TCP Server.
// Puerto: 48000
// Timeout Idle: 30 segundos.
TcpServerInit(48000, 30)
Nota: Se recomienda utilizar un valor de TimeoutIdle lo más pequeño posible, de tal forma que si no hay actividad por parte del cliente antes de ese periodo, la conexión se libere para otro potencial cliente.
Bajo este criterio, cada cliente debe enviar antes del tiempo TimeoutIdle algún dato para que la conexión permanezca abierta. Así mismo, el cliente puede cerrar la conexión en cualquier momento para liberarla (muy recomendado, si la misma no va a usarse por un periodo largo).
TcpServerGetNewId()
Retorna el Id de conexiones nuevas. En cada llamada retorna un Id diferente si hay conexiones nuevas,
de lo contrario retorna 0.
RETORNO:
- ( >0 ) = Id de conexión nueva
- ( 0 ) = No existen nuevas conexiones.
EJEMPLO:
new ConnId[TCPSERV_MAX_CONNECTIONS+1]
new Id
// Obtener todos los Id de conexión nuevas aceptadas.
while((Id=TcpServerGetNewId()) > 0)
{
// Actualizar y guardar Id en memoria con conexiones activas.
ConnId[Id] = Id;
}
En cada elemento del array ConnId se mantiene el Id de una conexión activa, caso contrario,
el valor del elemento es 0.
TcpServerSend(Id, Data[], Length=1)
Envía datos a través de una conexión TCP activa del servidor.
ENTRADAS:
- Id = Identificador de conexión.
- Data[] = Array con datos a enviar. Cada elemento representa un byte.
- Length = Numero de bytes a enviar (máximo 70 bytes).
RETORNO:
- ( 0 ) = Operación exitosa.
- ( -1 ) = Error en Id de conexión (conexión cerrada, no existe, etc).
- ( -2 ) = Error, existen datos pendientes para transmitir. Esperar.
- ( -3 ) = Error, Length excede el valor máximo a transmitir permitido.
- ( -20 ) = Error en dirección de Data[].
EJEMPLO:
new TxData[5] = {'H', 'e', 'l', 'l', 'o' }
// Enviar 5 bytes del array TxData[] usando la conexión Id=1.
TcpServerSend(1, TxData, 5)
TcpServerRead(Id, Data[], Max=1)
Lee los datos recibidos de una conexión TCP activa del servidor.
ENTRADAS:
- Id = Identificador de conexión.
- Data[] = Retorno en array con los datos leídos. Cada elemento representa un byte.
- Max = Máximo numero de bytes a copiar en Data[]. Si el numero de bytes recibidos es menor a Max, los elementos restantes de Data[] son llenados con el valor 0.
RETORNO:
- ( >0 ) = Operación exitosa, numero de bytes leídos.
- ( -1 ) = Error en Id de conexión (conexión cerrada, no existe, etc).
- ( -2 ) = Error, no hay datos pendientes para leer.
- ( -3 ) = Error, el valor Max excede el tamaño del buffer interno de recepción (máximo 70 bytes).
- ( -20 ) = Error en dirección de Data[].
EJEMPLO:
new RxData[10]
// Leer hasta 10 bytes del Id de conexión 1 y almacenar en RxData[].
if(TcpServerRead(1, RxData, 10) > 0)
{
// Si el primer byte recibido tiene el valor 88 conmutar RELAY1.
if(RxData[0] == 88)
{
RelayToggle(RELAY1)
}
}
TcpServerGetUnreadId()
Obtiene los Id de conexiones con datos no leídos. En cada llamada retorna un Id diferente si la conexión tiene
datos sin leer, de lo contrario retorna 0.
RETORNO:
- ( >0 ) = Id de conexión con datos no leídos
- ( 0 ) = No existen conexiones con datos sin leer.
EJEMPLO:
new TxData[5] = {'H', 'e', 'l', 'l', 'o' }
new RxData[10]
new Id
//
// Obtener conexiones con datos sin leer.
//
while((Id=TcpServerGetUnreadId()) > 0)
{
// Leer datos en RxData[], hasta 10 bytes.
TcpServerRead(Id, RxData, 10)
// Responder con un mensaje usando el Id de la conexión que recibió los datos.
TcpServerSend(Id, TxData, 5)
}
TcpServerGetDataSentId()
Obtiene los Id de conexiones que transmitieron datos exitosamente. En cada llamada retorna un Id diferente si la conexión transmitió los datos, de lo contrario retorna 0.
Esta función es útil para determinar conexiones que transmitieron los datos previamente cargados con TcpServerSend(). De esta forma, podemos continuar enviando los datos siguientes al cliente.
RETORNO:
- ( >0 ) = Id de conexión con datos transmitidos.
- ( 0 ) = No existen conexiones con datos transmitidos.
EJEMPLO:
new TxData[2]
new Sample
new Id
// Obtener conexiones con datos transmitidos.
while((Id=TcpServerGetDataSentId()) > 0)
{
// Generar nuevos datos leyendo datos del canal analógico 1.
// Enviar los 10 bits en bytes separados.
Sample = VinRead(1)
TxData[0] = Sample
TxData[1] = Sample >> 8
// Enviar muestra analógica
TcpServerSend(Id, TxData, 2)
}
TcpServerCheckUnreadId(Id)
Comprueba si una conexión tiene datos recibidos sin leer.
ENTRADAS:
- Id = Identificador de conexión.
RETORNO:
- ( 1 ) = Datos recibidos sin leer.
- ( 0 ) = No hay datos recibidos sin leer.
EJEMPLO:
new RxData[10]
// Comprobar si la conexión 1 tiene datos recibidos sin leer.
if(TcpServerCheckUnreadId(1))
{
// Leer datos en RxData[], hasta 10 bytes.
TcpServerRead(1, RxData, 10)
}
TcpServerCheckTxPendingId(Id)
Comprueba si una conexión tiene datos pendientes para transmitir.
ENTRADAS:
- Id = Identificador de conexión.
RETORNO:
- ( 1 ) = Datos pendientes para transmitir.
- ( 0 ) = No hay datos pendientes para transmitir.
EJEMPLO:
new TxData[5] = {'H', 'e', 'l', 'l', 'o' }
// Comprobar si la conexión 1 transmitió todos los datos y esta
// lista para transmitir nuevamente.
if(TcpServerCheckTxPendingId(1) == 0)
{
// Enviar datos.
TcpServerSend(1, TxData, 5)
}
TcpServerCheckClosedId(Id)
Comprueba si una conexión está cerrada.
ENTRADAS:
- Id = Identificador de conexión.
RETORNO:
- ( 1 ) = Conexión cerrada.
- ( 0 ) = Conexión activa.
EJEMPLO:
new TxData[5] = {'H', 'e', 'l', 'l', 'o' }
// Comprobar si la conexión 1 no está cerrada.
if(TcpServerCheckClosedId(1) == 0)
{
// Transmitir datos en la conexión abierta.
TcpServerSend(1, TxData, 5)
}
TcpServerAbortId(Id)
Aborta una conexión.
ENTRADAS:
- Id = Identificador de conexión.
RETORNO:
- ( 0 ) = Éxito, conexión pendiente para abortar.
- ( -1 ) = Error, conexión inválida (no existe, cerrada, etc).
EJEMPLO:
// Abortar conexión de entrada digital DIN1 esta activa.
if(DinValue(DIN1))
{
// Abortar conexión 1.
TcpServerAbortId(1)
}
TcpServerProcessId(Id)
Fuerza el procesamiento de una conexión activa inmediatamente. Si hay datos pendientes para enviar, los mismos serán transmitidos inmediatamente si es posible.
Esto evita esperar que el sistema procese la conexión (por defecto puede tardar hasta 0.5 segundos) y acelera la transmisión de datos.
ENTRADAS:
- Id = Identificador de conexión.
RETORNO:
- ( 1 ) = Conexión procesada.
- ( 0 ) = Error, conexión inválida (no existe, cerrada, etc).
EJEMPLO:
// Buffer de transmision.
new TxData[5] = {'H', 'e', 'l', 'l', 'o' }
// Enviar datos.
TcpServerSend(Id, TxData, 5)
// Forzar procesamiento de conexión, intentar enviar datos inmediatamente.
TcpServerProcessId(Id)
Nota: Si se necesita enviar muchos datos seguidos (muchas llamadas consecutivas a TcpServerSend()), se aconseja comprobar antes si fueron transmitidos previamente con TcpServerCheckTxPendingId(Id) o mediante el evento @OnTcpServerTx().
TcpServerGetMaxId()
Obtiene el numero máximo de conexiones permitidas en simultaneo por el servidor TCP/IP.
El valor retornado es idéntico al valor de la constante TCPSERV_MAX_CONNECTIONS, pero se recomienda utilizar esta función ya que la misma retorna el valor directamente desde el PLC, por lo tanto se actualiza con cada actualización de firmware, sin depender del entorno StxLadder.
RETORNO:
- Número máximo de conexiones simultáneas admitidas por el servidor.
EJEMPLO-1:
new Id
new TxData[5] = {'H', 'e', 'l', 'l', 'o' }
//
// Recorrer todas la posibles conexiones y enviar datos en cada una.
//
for(Id=1; Id <= TcpServerGetMaxId(); Id++)
{
// Comprobar si la conexión no está cerrada.
if(TcpServerCheckClosedId(Id) == 0)
{
// Transmitir datos en la conexión abierta.
TcpServerSend(Id, TxData, 5)
}
}
EJEMPLO-2:
new Id
//
// Recorrer todas la posibles conexiones y abortar todas.
//
for(Id=1; Id <= TcpServerGetMaxId(); Id++)
{
// Comprobar si la conexión no está cerrada.
if(TcpServerCheckClosedId(Id) == 0)
{
// Abortar conexión.
cpServerAbortId(Id)
}
}
TcpServerSetConnectedEvent()
Activa el evento @OnTcpServerConnected() que se llama cuando un cliente TCP se conecta inicialmente al servidor.
RETORNO:
- ( 0 ) = Éxito, evento activado.
- ( -1 ) = Error, evento no activado.
EJEMPLO:
//
// Almacena identificadores de conexiones.
// Cada elemento contiene el identificador de conexión (mayor a 0).
// Si la conexión esta activa es un valor entero positivo mayor a 0.
// Si la conexión no está activa, el elemento vale 0.
//
new ConnId[TCPSERV_MAX_CONNECTIONS+1]
PlcMain()
{
// ...
// Activar evento para conexión de cliente.
TcpServerSetConnectedEvent()
// ...
}
@OnTcpServerConnected()
{
new Id
// Obtener todos los Id con conexiones nuevas aceptadas.
while((Id=TcpServerGetNewId()) > 0)
{
// Bienvenido!
// Actualizar Id en memoria con conexiones activas.
ConnId[Id] = Id
}
}
Nota: Luego podemos recorrer el array ConnId[] e identificar cuales conexiones esta activas.
TcpServerSetClosedEvent()
Activa el evento @OnTcpServerClosed() que se llama cuando un cliente TCP cierra la conexión al servidor.
RETORNO:
- ( 0 ) = Éxito, evento activado.
- ( -1 ) = Error, evento no activado.
EJEMPLO:
//
// Almacena identificadores de conexiones.
// Cada elemento contiene el identificador de conexión (mayor a 0).
// Si la conexión esta activa es un valor entero positivo mayor a 0.
// Si la conexión no está activa, el elemento vale 0.
//
new ConnId[TCPSERV_MAX_CONNECTIONS+1]
PlcMain()
{
// ...
// Activar evento para cierre de conexión.
TcpServerSetClosedEvent()
// ...
}
@OnTcpServerClosed()
{
new Id
//
// Recorrer todas la posibles conexiones.
//
for(Id=1; Id <= TcpServerGetMaxId(); Id++)
{
// Actualizar conexiones cerradas.
if(TcpServerCheckClosedId(Id) == 0)
{
// Adiós!
ConnId[Id] = 0
}
}
}
Nota: Luego podemos recorrer el array ConnId[] e identificar cuales conexiones esta activas.
TcpServerSetRxEvent()
Activa el evento @OnTcpServerRx() que se llama cuando datos son recibidos de un cliente TCP remoto.
RETORNO:
- ( 0 ) = Éxito, evento activado.
- ( -1 ) = Error, evento no activado.
EJEMPLO:
// Buffer de recepción.
new RxData[10]
// Buffer de transmisión.
new TxData[5] = {'H', 'e', 'l', 'l', 'o' }
PlcMain()
{
// ...
// Activar evento para recepción de datos del cliente.
TcpServerSetRxEvent()
// ...
}
@OnTcpServerRx()
{
new Id
new Len
//
// Obtener conexiones con datos sin leer.
//
while((Id=TcpServerGetUnreadId()) > 0)
{
// Leer datos.
Len = TcpServerRead(Id, RxData, 10)
//
// Hacer algo con los datos recibidos en RxData[].
// La cantidad de bytes leídos se almacena en la variable 'Len'.
//
// Responder con un mensaje usando el Id de la conexión que recibió los datos.
TcpServerSend(Id, TxData, 5)
}
}
TcpServerSetTxEvent()
Activa el evento @OnTcpServerTx() que se llama cuando una conexión transmitió todos los datos pendiente.
RETORNO:
- ( 0 ) = Éxito, evento activado.
- ( -1 ) = Error, evento no activado.
EJEMPLO:
// Buffer de transmisión.
new TxData[5] = {'H', 'e', 'l', 'l', 'o' }
PlcMain()
{
// ...
// Activar evento para fin de transmisión de datos del cliente.
TcpServerSetTxEvent()
// ...
}
@OnTcpServerTx()
{
new Id
// Obtener conexiones con datos transmitidos.
while((Id=TcpServerGetDataSentId()) > 0)
{
// Transmitir nuevamente datos usando el Id de la conexión.
TcpServerSend(Id, TxData, 5)
}
}
TcpServerClrConnectedEvent()
TcpServerClrClosedEvent()
TcpServerClrRxEvent()
TcpServerClrTxEvent()
Cada una desactiva los siguientes eventos (si fueron previamente activados):
@OnTcpServerConnected()
@OnTcpServerClosed()
@OnTcpServerRx()
@OnTcpServerTx()
RETORNO:
- ( 0 ) = Éxito, evento desactivado.