aplicaciÓn scada comunicaciÓn tcp/ipdeeea.urv.cat/public/propostes/pub/pdf/1118pub.pdf · -...

145
APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP INGENIERÍA TÉCNICA INDUSTRIAL ESPECIALIDAD ELECTRÓNICA INDUSTRIAL AUTOR: Esteve Grau Pina PONENTE: Ernest Gil Dolcet FECHA: Junio 2009

Upload: vohuong

Post on 31-Jan-2018

239 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP

INGENIERÍA TÉCNICA INDUSTRIAL ESPECIALIDAD ELECTRÓNICA INDUSTRIAL AUTOR: Esteve Grau Pina

PONENTE: Ernest Gil Dolcet

FECHA: Junio 2009

Page 2: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

2

MEMORIA

DESCRIPTIVA

Page 3: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

3

ÍNDICE • Objetivos del proyecto ___________________________________________ 4 • Configuración de la conexión______________________________________ 5 • Fundamentos arquitectura TCP/IP___________________________________ 8

Introducción 11 El Protocolo Internet (Internet Protocol - IP) 12 Direccionamiento IP 13 Direcciones de red y de difusión 14 Resumen de las reglas especiales de direccionamiento 15 Protocolos de Ruteo (nivel IP) 15 Protocolo de Información de Ruteo (RIP) 16 Protocolo SPF abierto (OSPF) 17 Protocolos de resolución de direcciones 18 Protocolo de Asociación de Direcciones por Réplica (RARP) 18 Mensajes de error y control en IP (ICMP) 19 Protocolo de datagrama de usuario (UDP) 20 Protocolo de control de transmisión (TCP) 22 Puertos, conexiones y puntos extremos 24

• La interface socket_______________________________________________ 31 Introducción Sockets 32 Identificación de un socket 32 Tipos de sockets 34 Modelo de comunicación cliente – servidor 35 Proceso de conexión cliente – servidor 36 Modelo de programación 38 Byte order 39 Programación de sockets en Windows 40 Programación de sockets en Windows usando C++ y MFC 41

• Fundamentos sobre el control MSWinsockControl______________________ 43 • Diagramas de flujo_______________________________________________ 61 Introducción 62

Aplicación scada 63 Aplicación cliente lectura 64 Aplicación cliente escritura 65 Aplicación servidor 66

• Conclusiones_____________________________________________________ 68 • Referencias_____________________________________________________ 71

Page 4: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

4

OBJETIVOS DEL PROYECTO

Page 5: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

5

El propósito de este proyecto reside en la realización de una aplicación, realizada en Microsoft Visual C++ , que pueda realizar el control y monitorización remota de un proceso industrial. Los diferentes usuarios podrán realizar el control de dicho proceso de forma local, desde la misma planta, o de forma remota.

El tipo de red de ordenadores que se utiliza es cualquier tipo de red Ethernet basada en el protocolo TCP/IP. Así pues un ordenador servidor y cliente pueden realizar una conexión mediante una red WAN (Wide Area NetWork) como Internet o una red LAN (Local Area NetWork) como puede ser una intranet privada de una empresa.

Los empleados que quieran visualizar el proceso desde una ubicación exterior a la planta deberán poseer de un ordenador conectado a internet y poseer una identificación suministrada por la empresa.

También se ha contemplado la opción de incorporar una aplicación única donde, a través de internet, se podrá enviar la consigna deseada en el proceso industrial.

Las dos conexiones basadas en internet sólo estarán habilitadas cuando el usuario del ordenador donde se ubica el sistema captador de datos (SCADA) haya activado la opción de control remoto.

En la figura 1 se puede observar la aplicación del proceso industrial en la cual se ha basado este proyecto.

Figura1. Proceso industrial con aplicación Horno

Page 6: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

6

CONFIGURACIÓN DE LA CONEXIÓN

Page 7: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

7

El software realizado (Cliente.exe, Servidor.Exe) se debe instalar en un ordenador PC compatible con el sistema operativo Windows.

Para conseguir controlar remotamente el proceso se pueden utilizar diferentes configuraciones del hardware.

Según el caso, el hardware para conectarse a la red TCP/IP es diferente.

1. Intranet Local

Una Intranet es una red de ordenadores privados que utiliza tecnología Internet para compartir de forma segura cualquier información o programa del sistema operativo para evitar que cualquier usuario de Internet pueda ingresar . En la arquitectura de las Intranets se dividen el cliente y el servidor. El software cliente puede ser cualquier computadora local (servidor web o PC), mientras que el software servidor se ejecuta en una Intranet anfitriona. No es necesario que estos dos softwares, el cliente y el servidor, sean ejecutados en el mismo sistema operativo. Podría proporcionar una comunicación privada y exitosa en una organización.

Fig1.1 Ejemplo conexión intranet. 1

2. Intranet con conexión a Internet a través de un proxy

Enlazamos con la red TCP/IP con la tarjeta de red a nuestra Intranet Local y con la

1 Figura 1.1 www.connectingworks.com/software/intranets.php

Page 8: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

8

ayuda de un servidor proxy a Internet . En el contexto de las redes informáticas, el término proxy hace referencia a un programa o dispositivo que realiza una acción en representación de otro. Su finalidad más habitual es la de servidor proxy, que sirve para permitir el acceso a Internet a todos los equipos de una organización cuando sólo se puede disponer de un único equipo conectado, esto es, una única dirección IP.

Un proxy permite a otros equipos conectarse a una red de forma indirecta a través de él. Cuando un equipo de la red desea acceder a una información o recurso, es realmente el proxy quien realiza la comunicación y a continuación traslada el resultado al equipo inicial. En unos casos esto se hace así porque no es posible la comunicación directa y en otros casos porque el proxy añade una funcionalidad adicional, como puede ser la de mantener los resultados obtenidos (p.ej.: una página web) en una caché que permita acelerar sucesivas consultas coincidentes. Con esta denominación general de proxy se agrupan diversas técnicas.

Fig1.2 Ejemplo conexión con Proxy.

Page 9: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

9

3. Conexión a Internet a través de ISP

Conectarnos telefónicamente mediante un módem a un Proveedor de Servicios de

Internet ( ISP) que enlazará nuestro PC a la red Internet.

Un proveedor de servicios de Internet (o ISP, por la sigla en idioma inglés de Internet Service Provider) es una empresa dedicada a conectar a Internet a los usuarios, o las distintas redes que tengan, y a dar el mantenimiento necesario para que el acceso funcione correctamente. También ofrece servicios relacionados, como alojamiento web o registro de dominios, entre otros.

Fig1.2 Ejemplo conexión a internet mediante ISP. 2

2 Figura 1.1 www.kan-ed.org/network-intro

Page 10: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

10

ARQUITECTURA TCP/IP

Page 11: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

11

Introducción La arquitectura TCP/IP esta hoy en día ampliamente difundida, a pesar de ser una arquitectura de facto, en lugar de ser uno de los estándares definidos por la ISO, IICC, etc...

Esta arquitectura se empezó a desarrollar como base de la ARPANET (red de comunicaciones militar del gobierno de los EE.UU), y con la expansión de la INTERNET se ha convertido en una de las arquitecturas de redes más difundida.

Antes de continuar, pasemos a ver la relación de esta arquitectura con respecto al modelo de referencia OSI (Open Systems Interconnection) de la ISO.

Así como el modelo de referencia OSI posee siete niveles (o capas), la arquitectura TCP/IP viene definida por 4 niveles : el nivel de subred [enlace y físico], el nivel de interred [Red, IP], el protocolo proveedor de servicio [Transporte, TCP o UDP] , y el nivel de aplicación.

Page 12: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

12

El Protocolo Internet (Internet Protocol - IP) El protocolo IP es el principal del modelo OSI, así como parte integral del TCP/IP. Las tareas principales del IP son el direccionamiento de los datagramas de información y la administración del proceso de fragmentación de dichos datagramas.

El datagrama es la unidad de transferencia que el IP utiliza, algunas veces identificada en forma más específica como datagrama Internet o datagrama IP

Las características de este protocolo son :

NO ORIENTADO A CONEXIÓN

- Transmisión en unidades denominadas datagramas.

- Sin corrección de errores, ni control de congestión.

- No garantiza la entrega en secuencia.

Figura 1. Estructura simplificada de un datagrama IP

Page 13: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

13

La entrega del datagrama en IP no está garantizada porque ésta se puede retrasar, enrutar de manera incorrecta o mutilar al dividir y reensamblar los fragmentos del mensaje. Por otra parte, el IP no contiene suma de verificación para el contenido de datos del datagrama, solamente para la información del encabezado.

En cuanto al ruteo (encaminamiento) este puede ser :

- Paso a paso a todos los nodos

- Mediante tablas de rutas estáticas o dinámicas

Direccionamiento IP El TCP/IP utiliza una dirección de 32 bits para identificar una máquina y la red a la cual está conectada. Unicamente el NIC (Centro de Información de Red) asigna las direcciones IP (o Internet), aunque si una red no está conectada a Internet, dicha red puede determinar su propio sistema de numeración.

Hay cuatro formatos para la dirección IP, cada uno de los cuales se utiliza dependiendo del tamaño de la red. Los cuatro formatos, Clase A hasta Clase D (aunque últimamente se ha añadido la Clase E para un futuro) aparecen en la figura :

CLASE A

CLASE B

CLASE C

CLASE D

Conceptualmente, cada dirección está compuesta por un par (RED (netid), y Dir. Local (hostid)) en donde se identifica la red y el host dentro de la red.

La clase se identifica mediante las primeras secuencias de bits, a partir de los 3 primeros bits (de orden más alto).

Page 14: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

14

Las direcciones de Clase A corresponden a redes grandes con muchas máquinas. Las direcciones en decimal son 0.1.0.0 hasta la 126.0.0.0 (lo que permite hasta 1.6 millones de hosts).

Las direcciones de Clase B sirven para redes de tamaño intermedio, y el rango de direcciones varía desde el 128.0.0.0 hasta el 191.255.0.0. Esto permite tener 16320 redes con 65024 host en cada una.

Las direcciones de Clase C tienen sólo 8 bits para la dirección local o de anfitrión (host) y 21 bits para red. Las direcciones de esta clase están comprendidas entre 192.0.1.0 y 223.255.255.0, lo que permite cerca de 2 millones de redes con 254 hosts cada una.

Por último, las direcciones de Clase D se usan con fines de multidifusión, cuando se quiere una difusión general a más de un dispositivo. El rango es desde 224.0.0.0 hasta 239.255.235.255.

Cabe decir que, las direcciones de clase E (aunque su utilización será futura) comprenden el rango desde 240.0.0.0 hasta el 247.255.255.255.

Por tanto, las direcciones IP son cuatro conjuntos de 8 bits, con un total de 32 bits. Por comodidad estos bits se representan como si estuviesen separados por un punto, por lo que el formato de dirección IP puede ser red.local.local.local para Clase A hasta red.red.red.local para clase C.

A partir de una dirección IP, una red puede determinar si los datos se enviarán a través de una compuerta (GTW, ROUTER). Obviamente, si la dirección de la red es la misma que la dirección actual (enrutamiento a un dispositivo de red local, llamado host directo), se evitará la compuerta ; pero todas las demás direcciones de red se enrutarán a una compuerta para que salgan de la red local. La compuerta que reciba los datos que se transmitirán a otra red, tendrá entonces que determinar el enrutamiento can base en la dirección IP de los datos y una tabla interna que contiene la información de enrutamiento.

Otra de las ventajas que ofrece el direccionamiento IP es el uso de direcciones de difusión (broadcast addresses), que hacen referencia a todos los host de la misma red. Según el estándar, cualquier dirección local (hostid) compuesta toda por 1s está reservada para difusión (broadcast). Por ejemplo, una dirección que contenga 32 1s se considera un mensaje difundido a todas las redes y a todos los dispositivos. Es posible difundir en todas las máquinas de una red alterando a 1s toda la dirección local o de anfitrión (hostid), de manera que la dirección 147.10.255.255 para una red de Clase B se recibiría en todos los dispositivos de dicha red ; pero los datos no saldrían de dicha red.

Direcciones de red y difusión La mayor ventaja de la codificación de información de red en las direcciones de red en IP tiene una ventaja importante: hacer posible que exista un ruteo eficiente. Otra ventaja es que las direcciones de red IP se pueden referir tanto a redes como a anfitriones (hosts). Por regla, nunca se asigna un campo hostID igual a 0 a un anfitrión individual. En vez de eso, una dirección IP con campo hostID a 0 se utiliza para referirse a la red en sí misma.

Page 15: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

15

En resumen:

Las direcciones IP se pueden utilizar para referirse a redes así como a anfitriones individuales. Por regla, una dirección que tiene todos los bits del campo hostID a 0, se reserva para referirse a la red en sí misma.

Otra ventaja significativa del esquema de direccionamiento IP es que éste incluye una dirección de difusión (BROADCAST) que se refiere a todos los anfitriones de la red. De acuerdo con el estándar, cualquier campo hostID consistente solamente en 1s, esta reservado para la difusión (BROADCAST). Esto permite que un sistema remoto envíe un sólo paquete que será publidifundido en la red especificada.

Resumen de reglas especiales de direccionamiento En la práctica, el IP utiliza sólo unas cuantas combinaciones de ceros ("está") o unos ("toda"). Las posibilidades son las siguientes :

TODOS 0 - Éste anfitrión (permitido solamente en el arranque del sistema, pero nunca es una dirección válida de destino.

TODOS 0 | ANFITRIÓN - Anfitrión en ésta RED (solo para arranque, no como dir. válida)

TODOS 1 - Difusión limitada (red local) (Nunca es una dirección válida de origen)

RED | TODOS 1 - Difusión dirigida para RED (" " )

127 | NADA (a menudo 1) - LOOPBACK (nunca debe aparecer en una red)

Como se menciona arriba, la utilización de todos los ceros para la red sólo está permitida durante el procedimiento de iniciación de la maquina. Permite que una máquina se comunique temporalmente. Una vez que la máquina "aprende" su red y dir. IP correctas, no debe utilizar la red 0.

Protocolos de ruteo (nivel IP). A dos routers dentro de un sistema autónomo se les denomina "interiores" con respecto a otro.

En redes como InterNet que tienen varias rutas físicas, los administradores por lo general seleccionan una de ellas como ruta primaria. Los ruteadores interiores normalmente se comunican con otros, intercambian información de accesibilidad a red o información de ruteo de red, a partir de la cual la accesibilidad se puede deducir.

A diferencia de esto, en la comunicación de un router exterior no se ha desarrollado un solo protocolo que se utilice con los sistemas autónomos.

Page 16: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

16

Protocolo de Información de Ruteo (RIP). Uno de los I.G.P. (Interior Gateway Protocol) más ampliamente utilizados es el RIP, también conocido con el nombre de un programa que lo implementa (el routeD o Route Daemon).

El protocolo RIP es consecuencia directa de la implantación del ruteo de vector-distancia para redes locales. En principio, divide las máquinas participantes en activas o pasivas (silenciosas). Los routers activos anuncian sus rutas a los otros; las máquinas pasivas listan y actualizan sus rutas con base a estos anuncios. Sólo un router puede correr RIP en modo activo de modo que un anfitrión deberá correr el RIP en modo pasivo.

Un router con RIP en activo difunde un mensaje cada 30 segundos, éste mensaje contiene información tomada de la base de datos de ruteo actualizada. Cada mensaje consiste en pares, donde cada par contiene una dirección IP y un entero que representa la distancia hacia esta red (el IP address).

El RIP por tanto hace uso de un vector de distancias, con una métrica por número de saltos donde se considera que 16 saltos o más es infinito. De esta manera, el número de saltos (hops number) o el contador de saltos (hop count) a lo largo de una trayectoria desde una fuente dada hacia un destino dado hace referencia al número de routers que un datagrama encontrará a lo largo de su trayectoria. Por tanto lo que se hace es utilizar el conteo de saltos para calcular la trayectoria óptima (aunque esto no siempre produce resultados buenos).

Para prevenir que dos routers oscilen entre dos o más trayectorias de costos iguales, RIP especifica que se deben conservar las rutas existentes hasta que aparezca una ruta nueva con un costo estrictamente menor.

Si falla el primer router que anuncia la ruta RIP especifica que todas las escuchas deben asociar un tiempo límite a las rutas que aprenden por medio de RIP. Cuando un router instala una ruta en su tabla, inicia un temporizador para tal ruta. Este tiempo debe iniciarse cada vez que el router recibe otro mensaje RIP anunciando la ruta. La ruta queda invalidada si transcurren 180 segundos sin que el router haya recibido un anuncio nuevamente.

RIP debe manejar tres tipos de errores ocasionados por los algoritmos subyacentes. En primer lugar, dado que el algoritmo no especifica detección de ciclos de ruteo, RIP debe asumir que los participantes son confiables o deberá tomar precauciones para prevenir los ciclos. En segundo lugar, para prevenir inestabilidades, RIP debe utilizar un valor bajo para la distancia máxima posible (RIP utiliza 16 saltos como medida máxima). Esto implica que para una red como Internet, los administradores deben dividirla en secciones o utilizar un protocolo alternativo. En tercer y último lugar, el algoritmo vector-distancia empleado por RIP crea un problema de convergencia lenta o conteo al infinito, problema en el cual aparecerán inconsistencias, debido a que los mensajes de actualización de ruteo se difunden lentamente a través de la red. Seleccionando un infinito pequeño (16) se ayuda a limitar la convergencia lenta, pero NO se elimina.

Page 17: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

17

La inconsistencia en la tabla de ruteo no es exclusiva de RIP, éste es un problema fundamental que se presenta en todo protocolo con algoritmos vector-distancia, en el que los mensajes de actualización transportan únicamente pares de redes de destino y distancias hacia estas redes.

Solución al problema de la convergencia lenta:

Es posible resolver el problema de la convergencia lente mediante una técnica conocida como actualización de horizonte separado (split horizon update). Cuando se utilizan horizontes separados, un router registra la interfaz por la que ha recibido una ruta particular y no difunde la información acerca de la ruta de regreso sobre la misma interfaz. Con esto evitamos que la información "negativa" no sea difundida con rapidez.

Una de las técnicas finales para resolver el problema de la convergencia lenta se conoce como Poison Reverse. Una vez que una conexión desaparece, el router anuncia la conexión conservando la entrada de información por varios periodos de actualización e incluye un costo infinito en la difusión. Para hacer el Poison Reverse más efectivo, se debe combinar con las Triggered Updates (actualizaciones activadas) que obligan al router a que envíe una difusión inmediatamente al recibir "malas noticias", en lugar de esperar el próximo periodo de difusión. Al enviar una actualización inmediatamente, un router minimiza el tiempo en que es vulnerable por recibir "buenas noticias".

Protocolo SPF abierto (OSPF). El algoritmo de propagación de rutas abierto (OSPF) propone los siguientes objetivos:

- Tecnología de estado de enlaces.

- Soporta tipos de servicio (los administradores pueden instalar múltiples rutas hacia un destino dad, uno por cada tipo de servicio).

- Proporciona un balance de cargas entre rutas de igual peso (Si un administrador especifica múltiples rutas hacia un destino con el mismo costo, el OSPF distribuye el tráfico entre todas las rutas de la misma manera. Nótese que el RIP calcula una sola ruta para cada destino).

- Partición en áreas.

- Propagación de modificaciones entre los enlaces.

- Localización automática de routers vecinos.

- Propagación de rutas aprendidas de fuentes externas.

- Routers designados en redes multiacceso.

Page 18: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

18

Protocolo de resolución de direcciones El objetivo es diseñar un software de bajo nivel que oculte las direcciones físicas (MAC) y permita que programas de un nivel más alto trabajen sólo con direcciones IP. La transformación de direcciones se tiene que realizar en cada fase a lo largo del camino, desde la fuente original hasta el destino final. En particular, surgen dos casos. Primero, en la última fase de entrega de un paquete, éste se debe enviar a través de una red física hacia su destino final. La computadora que envía el paquete tiene que transformar la dirección IP de destino final en su dirección física (MAC). Segundo, en cualquier punto del camino, de la fuente al destino, que no sea la fase final, el paquete se debe enviar hacia un router intermedio. Por lo tanto, el transmisor tiene que transformar la dirección IP del router en una dirección física.

El problema de transformar direcciones de alto nivel en direcciones físicas se conoce como problema de asociación de direcciones (Address Resolution Problem). Este problema se suele resolver, normalmente, mediante tablas en cada máquina que contienen pares de direcciones, de alto nivel y físicas.

En el problema de asociación de direcciones en TCP/IP para redes con capacidad de difusión como Ethernet, se utiliza un protocolo de bajo nivel para asignar direcciones en forma dinámica y evitar así la utilización de una tabla de conversiones. Este protocolo es conocido como Protocolo de Asociación de Direcciones (ARP - Address Resolution Protocol). La idea detrás de la asociación dinámica con ARP es muy sencilla: cuando un host A quiere definir la dirección IP (IPb), transmite por difusión (broadcast) un paquete especial que pide al anfitrión (host) que posee la dirección IP (IPb), que responda con su dirección física (Pb). Todos los anfitriones reciben la solicitud, incluyendo a B, pero sólo B reconoce su propia dirección IP y envía una respuesta que contiene su dirección física. Cuando A recibe la respuesta, utiliza la dirección física para enviar el paquete IP directamente a B. En resumen:

El ARP permite que un anfitrión encuentre la dirección física de otro anfitrión dentro de la misma red física con sólo proporcionar la dirección IP de su objetivo.La información se guarda luego en una tabla ARP de orígenes y destinos.

Protocolo de Asociación de Direcciones por Réplica (RARP). Una máquina sin disco utiliza un protocolo TCP/IP para internet llamado RARP (Protocolo Inverso de Asociación de Direcciones) o Reverse Address Resolution Protocol, a fin de obtener su dirección IP desde un servidor.

En el arranque del sistema, una máquina de estas características (sin HDD permanente) debe contactar con un servidor para encontrar su dirección IP antes de que se pueda

Page 19: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

19

comunicar por medio del TCP/IP. El protocolo RARP utiliza el direccionamiento físico de red para obtener la dirección IP de la máquina. El mecanismo RARP proporciona la dirección hardware física de la máquina de destino para identificar de manera única el procesador y transmite por difusión la solicitud RARP. Los servidores en la red reciben el mensaje, buscan la transformación en una tabla (de manera presumible en su almacenamiento secundario) y responden al transmisor. Una vez que la máquina obtiene su dirección IP, la guarda en memoria y no vuelve a utilizar RARP hasta que se inicia de nuevo.

Mensajes de error y control en IP (ICMP). Como hemos visto anteriormente, el Protocolo Internet (IP) proporciona un servicio de entrega de datagramas, no confiable y sin conexión, al hacer que cada router direccione datagramas. Si un router no puede, por ejemplo, rutear o entregar un datagrama, o si el router detecta una condición anormal que afecta su capacidad para direccionarlo (v.q., congestionamiento de la red), necesita informar a la fuente original para que evite o corrija el problema.

Para permitir que los routers de una red reporten los errores o proporcionen información sobre circunstancias inesperadas, se agregó a la familia TCP/IP un mecanismo de mensajes de propósito especial, el Protocolo de Mensajes de Control Internet (ICMP). El ICMP permite que los routers envíen mensajes de error o de control hacia otros routers o anfitriones, proporcionando una comunicación entre el software de IP en una máquina y el mismo software en otra.

Cuando un datagrama causa un error, el ICMP sólo puede reportar la condición del error a la fuente original del datagrama; la fuente debe relacionar el error con un programa de aplicación individual o debe tomar alguna otra acción para corregir el problema.

Formato de los mensajes ICMP:

Aunque cada mensaje ICMP tiene su propio formato, todos comienzan con los mismos tres campos; un campo TYPE (TIPO) de mensaje, de 8 bits y números enteros, que identifica el mensaje; un campo CODE (CODIGO), de 8 bits, que proporciona más información sobre el tipo de mensaje, y una campo CHECKSUM (SUMA DE VERIFICACIÓN), de 16 bits. Además, los mensajes ICMP que reportan errores siempre incluyen el encabezado y los primeros 64 bits de datos del datagrama que causó el problema.

La razón de regresar más que el encabezado del datagrama únicamente es para permitir que el receptor determine de manera más precisa qué protocolo(s) y qué programa de aplicación son responsables del datagrama.

El campo TYPE de ICMP define el significado del mensaje así como su formato. Los tipos incluyen:

Page 20: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

20

CAMPO TYPE Tipo de Mensaje ICMP

0 Respuesta de ECO

3 Destino inaccesible

4 Disminución de origen (source quench -datagrama

eliminado por congestión)

5 Redireccionar (cambiar una ruta)

8 Solicitud de ECO

11 Tiempo excedido para un datagrama

12 Problema de parámetros de un datagrama

13 Solicitud de TIMESTAMP

14 Respuesta de TIMESTAMP

15 Solicitud de Información (obsoleto)

16 Respuesta de Información (obsoleto)

17 Solicitud de Máscara de dirección

18 Respuesta de máscara de dirección

Una de las herramientas de depuración más utilizadas incluye los mensajes ICMP de echo request (8) y echo reply (0). En la mayoría de los sistemas, el comando que llama el usuario para enviar solicitudes de eco ICMP se conoce como ping.

Protocolo de datagrama de usuario (UPD) La mayoría de los Sistemas Operativos actuales soportan multiprogramación. Puede parecer natural decir que un proceso es el destino final de un mensaje. Sin embargo, especificar que un proceso en particular en una máquina en particular es el destino final para un datagrama es un poco confuso. Primero, por que los procesos se crean y se destruyen dinámicamente, los transmisores rara vez saben lo suficiente para identificar un proceso en otra máquina. Segundo, nos gustaría poder reemplazar los procesos que reciben datagramas, sin tener que informar a todos los transmisores (v.q. reiniciar la máquina puede cambiar todos los PID de los procesos). Tercero, necesitamos identificar los destinos de las funciones que implantan sin conocer el proceso que implanta la función (v.q. permitir que un transmisor contacte un servidor de ficheros sin saber qué proceso en la máquina de destino implanta la función de FS).

En vez de pensar en un proceso como destino final, imaginaremos que cada máquina contiene un grupo de puntos abstractos de destino, llamados puertos de protocolo. Cada puerto de protocolo se identifica por medio de un número entero positivo.

Page 21: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

21

Para comunicarse con un puerto externo, un transmisor necesita saber tanto la dirección IP de la máquina de destino como el número de puerto de protocolo del destino dentro de la máquina.

El UDP proporciona el mecanismo primario que utilizan los programas de aplicación para enviar datagramas a otros programas de aplicación. El UDP proporciona puertos de protocolo utilizados para distinguir entre muchos programas que se ejecutan en la misma máquina. Esto es, además de los datos, cada mensaje UDP contiene tanto en número de puerto de destino como el número de puerto origen, haciendo posible que el software UDP en el destino entregue el mensaje al receptor correcto y que éste envíe una respuesta.

El UDP utiliza el Protocolo Internet subyacente para transportar un mensaje de una máquina a otra y proporciona la misma semántica de entrega de datagramas, sin conexión y no confiable que el IP. No emplea acuses de recibo para asegurarse de que llegan mensajes, no ordena los mensajes entrantes, ni proporciona retroalimentación para controlar la velocidad del flujo de información entre las máquinas. Por tanto, los mensajes UDP se pueden perder, duplicar o llegar sin orden. Además, los paquetes pueden llegar más rápido de lo que el receptor los puede procesar. En resumen:

El UDP proporciona un servicio de entrega sin conexión y no confiable, utilizando el IP para transportar mensajes entre máquinas. Emplea el IP para llevar mensajes, pero agrega la capacidad para distinguir entre varios destinos dentro de la computadora anfitrión.

Formato de los mensajes UDP:

Cada mensaje UDP se conoce como datagrama de usuario. Conceptualmente, un datagrama de usuario consiste en dos partes: un encabezado UDP y un área de datos UDP. El encabezado se divide en cuatro campos de 16 bits, que especifican el puerto desde el que se envió el mensaje, el puerto para el que se destina el mensaje, la longitud el mensaje y una suma de verificación UDP.

Figura 2. Estructura simplificada de UDP

Page 22: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

22

Figura 3. Datagrama UDP/IP completo. Relación entre el datagrama IP y el datagrama UDP

Protocolo de control de transmisión (TCP)

Servicio de Transporte de Flujo Confiable

Figura 4. Estructura básica de un paquete TCP/IP

Figura 5. Relación entre un datagrama IP y un segmento TCP

Page 23: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

23

En las secciones anteriores hemos visto el servicio de entrega de paquetes sin conexión y no confiable, que forma la base para toda comunicación en InterNet, así como el protocolo IP que lo defina.

Ahora veremos el segundo servicio más importante y mejor conocido a nivel de red, la entrega de flujo confiable (Reliable Stream Transport), así como el Protocolo de Control de Transmisión (TCP) que lo define.

En el nivel más bajo, las redes de comunicación proporcionan una entrega de paquetes no confiable. Los paquetes se pueden perder o destruir debido a errores (falla el hardware, sobrecarga de la red,...). Las redes que rutean dinámicamente los paquetes pueden entregarlos en desorden, con retraso o duplicados. En el nivel más alto, los programas de aplicación a menudo necesitan enviar grandes volúmenes de datos de una computadora a otra. Utilizar un sistema de entrega de conexión y no confiable para transferencias de grandes volúmenes de información resulta ser la peor opción. Debido a esto, el TCP se ha vuelto un protocolo de propósito general para estos casos.

La interfaz entre los programas de aplicación y la entrega confiable (es, decir, las características del TCP) se caracterizan por cinco funciones :

Servicio Orientado a Conexión : El servicio de entrega de flujo en la máquina destino pasa al receptor exactamente la misma secuencia de bytes que le pasa el transmisor en la máquina origen.

Conexión de Circuito Virtual : Durante la transferencia, el software de protocolo en las dos máquinas continúa comunicándose para verificar que los datos se reciban correctamente. Si la comunicación no se logra por cualquier motivo (v.q. falla el hardware de red), ambas máquinas detectarán la falla y la reportarán a los programas apropiados de aplicación. Se utiliza el término circuito virtual para describir dichas conexiones porque aunque los programas de aplicación visualizan la conexión como un circuito dedicado de hardware, la confiabilidad que se proporciona depende del servicio de entrega de flujo.

Transferencia con Memoria Intermedia : Los programas de aplicación envían un flujo de datos a través del circuito virtual pasando repetidamente bytes de datos al software de protocolo. Cuando se transfieren datos, cada aplicación utiliza piezas del tamaño que encuentre adecuado, que pueden ser tan pequeñas como un byte. En el extremo receptor, el software de protocolo entrega bytes del flujo de datos en el mismo orden en que se enviaron, poniéndolos a disposición del programa de aplicación receptor tan pronto como se reciben y se verifican. El software de protocolo puede dividir el flujo en paquetes, independientemente de las piezas que transfiera el programa de aplicación. Para hacer eficiente la transferencia y minimizar el tráfico de red, las implantaciones por lo general recolectan datos suficientes de un flujo para llenar un datagrama razonablemente largo antes de enviarlo. Por lo tanto, inclusive si el programa de aplicación genera el flujo un byte a la vez, la transferencia a través de la red puede ser sumamente eficiente. De forma similar, si el programa de aplicación genera bloques de datos muy largos, el software

Page 24: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

24

de protocolo puede dividir cada bloque en partes más pequeñas para su transmisión. Para aplicaciones en las que los datos de deben entregar aunque no se llene una memoria intermedia, el servicio de flujo proporciona un mecanismo de empuje o push que las aplicaciones utilizan para forzar una transferencia. En el extremo transmisor, el push obliga al software de protocolo a transferir todos los datos generados sin tener que esperar a que se llene una memoria intermedia. Sin embargo, la función de push sólo garantiza que los datos se transferirán, por tanto, aún cuando la entrega es forzada, el software de protocolo puede dividir el flujo en formas inesperadas (v.q. el transmisor puede reducirlo en caso de congestión).

Flujo no estructurado : Posibilidad de enviar información de control junto a datos.

Conexión Full Duplex : Se permite la transferencia concurrente en ambas direcciones. Desde el punto de vista de un proceso de aplicación, una conexión full duplex permite la existencia de dos flujos independientes que se mueven en direcciones opuestas, sin ninguna interacción aparente. Esto ofrece una ventaja : el software subyacente de protocolo puede enviar datagramas de información de control de flujo al origen, llevando datos en la dirección opuesta. Este procedimiento de carga, transporte y descarga REDUCE EL TRAFICO en la red.

Transferencia sin errores. Hemos visto que el servicio de entrega de flujo confiable garantiza la entrega de los datos enviados de una máquina a otra sin pérdida o duplicación. Surge ahora la pregunta contradictoria: ¿ Cómo puede el software subyacente de protocolo proporcionar una transferencia confiable si el sistema subyacente de comunicación sólo ofrece una entrega NO confiable de paquetes ?.

La respuesta es complicada, pero la mayor parte de los protocolos confiables utilizan una técnica fundamental conocida como acuse de recibo positivo con retransmisión. La técnica requiere que un receptor se comunique con el origen y le envíe un mensaje de acuse de recibo (ACK) conforme recibe los datos (ver los primeros temas para una descripción más detallada). El transmisor guarda un registro de cada paquete que envía y espera un ACK antes de enviar el siguiente paquete. El transmisor también arranca un temporizador cuando envía un paquete y lo retransmite si dicho temporizador expira antes de que llegue un ACK.

El problema final de la confiabilidad surge cuando un sistema subyacente de entrega de paquetes los duplica. Los duplicados también pueden surgir cuando las redes tienen grandes retrasos que provocan la retransmisión prematura. Para evitar la confusión causada por ACKs retrasados o duplicados, los protocolos de acuses de recibo positivos envían los números de secuencia dentro de los ACKs, para que el receptor pueda asociar correctamente los acuses de recibo con los paquetes.

Pero, como casi todo en esta vida es un problema tras otro, el TCP no iba a ser menos ; uno de los problemas que acarrea lo anterior es que un protocolo simple de acuses de recibo positivos ocupa una cantidad sustancial de ancho de banda de red debido a que debe retrasar

Page 25: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

25

el envío de un nuevo paquete hasta que reciba un ACK del paquete anterior.

La solución está en otra técnica conocida como ventana deslizante, que es una forma más compleja de acuse de recibo positivo y retransmisión. Los protocolos de ventana deslizante utilizan el ancho de banda de red de mejor forma al permitir que el transmisor envíe varios paquetes sin esperar el ACK (remitirse a capítulos anteriores para una descripción de éste método).

Puertos, conexiones y puntos extremos. Al igual que el UDP, el TCP reside sobre el IP en el esquema de estratificación por capas de protocolos. El TCP permite que varios programas de aplicación en una máquina se comuniquen de manera concurrente y realiza el demultiplexado del tráfico TCP entrante entre los programas de aplicación. Así mismo, al igual que el UDP, el TCP utiliza números de puerto de protocolo para identificar el destino final dentro de una máquina. Cada puerto tiene asignado un número entero pequeño utilizado para identificarlo.

Para comprender el significado de un puerto hay que pensar de cada puerto como en una cola de salida en la que el software de protocolo coloca los datagramas entrantes, aunque en realidad los puertos TCP son más complejos, ya que un número de puerto no corresponde a un sólo objeto. El TCP utiliza la conexión, no el puerto de protocolo, como su abstracción fundamental ; las conexiones se identifican por medio de un par de puntos extremos.

Un punto extremo es un par de números enteros (host, puerto), en donde host es la dirección IP de un anfitrión y puerto es el un puerto TCP en dicho anfitrión.

Las conexiones vienen definidas por dos puntos extremos, y es más : la abstracción de la conexión para TCP permite que varias conexiones compartan un punto extremo (por ejemplo, varias conexiones en los mismos puertos). Esto es posible a que el TCP identifica una conexión por medio de un par de puntos extremos, y por eso varias conexiones en la misma máquina pueden compartir un número de puerto TCP.

El TCP combina la asignación dinámica y estática de puertos mediante un conjunto de asignación de puertos bien conocidos para programas llamados con frecuencia, pero la salida de la mayor parte de los números disponibles para el sistema se asigna conforme los programas lo necesitan.

La siguiente tabla muestra un ejemplo de números de puerto TCP asignados actualmente.

Puerto/protocolo Descripción

n/d / GRE GRE (protocolo IP 47) Enrutamiento y acceso remoto

n/d / ESP IPSec ESP (protocolo IP 50) Enrutamiento y acceso remoto

n/d / AH IPSec AH (protocolo IP 51) Enrutamiento y acceso remoto

1/tcp Multiplexor TCP

Page 26: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

26

7/tcp Protocolo Echo (Eco) Reponde con eco a llamadas remotas

7/udp Protocolo Echo (Eco) Reponde con eco a llamadas remotas

9/tcp Protocolo Discard Elimina cualquier dato que recibe

9/udp Protocolo Discard Elimina cualquier dato que recibe

13/tcp Protocolo Daytime Fecha y hora actuales

17/tcp Quote of the Day (Cita del Día)

19/tcp Protocolo Chargen Generador de caractéres

19/udp Protocolo Chargen Generador de caractéres

20/tcp FTP File Transfer Protocol (Protocolo de Transferencia de Ficheros) –datos

21/tcp FTP File Transfer Protocol (Protocolo de Transferencia de Ficheros) –control

22/tcp SSH, scp, SFTP

23/tcp Telnet comunicaciones de texto inseguras

25/tcp SMTP Simple Mail Transfer Protocol (Protocolo Simple de Transferencia de Correo)

37/tcp time

43/tcp nicname

37/tcp time

53/tcp DNS Domain Name System (Sistema de Nombres de Dominio)

53/udp DNS Domain Name System (Sistema de Nombres de Dominio)

67/udp BOOTP BootStrap Protocol (Server), también usado por DHCP

68/udp BOOTP BootStrap Protocol (Client), también usado por DHCP

69/udp TFTP Trivial File Transfer Protocol (Protocolo Trivial de Transferencia de Ficheros)

70/tcp Gopher

79/tcp Finger

80/tcp HTTP HyperText Transfer Protocol (Protocolo de Transferencia de HiperTexto) (WWW)

Page 27: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

27

88/tcp Kerberos Agente de autenticación

110/tcp POP3 Post Office Protocol (E-mail)

111/tcp sunrpc

113/tcp ident (auth) antiguo sistema de identificación

119/tcp NNTP usado en los grupos de noticias de usenet

123/udp NTP Protocolo de sincronización de tiempo

123/tcp NTP Protocolo de sincronización de tiempo

135/tcp epmap

137/tcp NetBIOS Servicio de nombres

137/udp NetBIOS Servicio de nombres

138/tcp NetBIOS Servicio de envío de datagramas

138/udp NetBIOS Servicio de envío de datagramas

139/tcp NetBIOS Servicio de sesiones

139/udp NetBIOS Servicio de sesiones

143/tcp IMAP4 Internet Message Access Protocol (E-mail)

161/tcp SNMP Simple Network Management Protocol

161/udp SNMP Simple Network Management Protocol

162/tcp SNMP-trap

162/udp SNMP-trap

177/tcp XDMCP Protocolo de gestión de displays en X11

177/udp XDMCP Protocolo de gestión de displays en X11

389/tcp LDAP Protocolo de acceso ligero a Bases de Datos

389/udp LDAP Protocolo de acceso ligero a Bases de Datos

443/tcp HTTPS/SSL usado para la transferencia segura de páginas web

445/tcp Microsoft-DS (Active Directory, compartición en Windows, gusano Sasser, Agobot)

445/udp Microsoft-DS compartición de ficheros

500/udp IPSec ISAKMP, Autoridad de Seguridad Local

Page 28: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

28

512/tcp exec

513/tcp login

514/udp syslog usado para logs del sistema

520/udp RIP

591/tcp FileMaker 6.0 (alternativa para HTTP, ver puerto 80)

631/tcp CUPS sistema de impresión de Unix

666/tcp identificación de Doom para jugar sobre TCP

993/tcp IMAP4 sobre SSL (E-mail)

995/tcp POP3 sobre SSL (E-mail)

1080/tcp SOCKS Proxy

1337/tcp suele usarse en máquinas comprometidas o infectadas

1352/tcp IBM Lotus Notes/Domino RCP

1433/tcp Microsoft-SQL-Server

1434/tcp Microsoft-SQL-Monitor

1434/udp Microsoft-SQL-Monitor

1494/tcp Citrix MetaFrame Cliente ICA

1512/tcp WINS

1521/tcp Oracle listener por defecto

1701/udp Enrutamiento y Acceso Remoto para VPN con L2TP.

1723/tcp Enrutamiento y Acceso Remoto para VPN con PPTP.

1761/tcp Novell Zenworks Remote Control utility

1863/tcp MSN Messenger

1935/??? FMS Flash Media Server

2049/tcp NFS Archivos del sistema de red

2082/tcp CPanel puerto por defecto

2086/tcp Web Host Manager puerto por defecto

2427/upd Cisco MGCP

Page 29: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

29

3030/tcp NetPanzer

3030/upd NetPanzer

3128/tcp HTTP usado por web caches y por defecto en Squid cache

3128/tcp NDL-AAS

3306/tcp MySQL sistema de gestión de bases de datos

3389/tcp RDP (Remote Desktop Protocol)

3396/tcp Novell agente de impresión NDPS

3690/tcp Subversion (sistema de control de versiones)

4662/tcp eMule (aplicación de compartición de ficheros)

4672/udp eMule (aplicación de compartición de ficheros)

4899/tcp RAdmin (Remote Administrator), herramienta de administración remota (normalmente troyanos)

5000/tcp Universal plug-and-play

5060/udp Session Initiation Protocol (SIP)

5190/tcp AOL y AOL Instant Messenger

5222/tcp XMPP/Jabber conexión de cliente

5223/tcp XMPP/Jabber puerto por defecto para conexiones de cliente SSL

5269/tcp XMPP/Jabber conexión de servidor

5432/tcp PostgreSQL sistema de gestión de bases de datos

5517/tcp Setiqueue proyecto SETI@Home

5631/tcp PC-Anywhere protocolo de escritorio remoto

5632/udp PC-Anywhere protocolo de escritorio remoto

5400/tcp VNC protocolo de escritorio remoto (usado sobre HTTP)

5500/tcp VNC protocolo de escritorio remoto (usado sobre HTTP)

5600/tcp VNC protocolo de escritorio remoto (usado sobre HTTP)

5700/tcp VNC protocolo de escritorio remoto (usado sobre HTTP)

5800/tcp VNC protocolo de escritorio remoto (usado sobre HTTP)

5900/tcp VNC protocolo de escritorio remoto (conexión normal)

Page 30: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

30

6000/tcp X11 usado para X-windows

6112/udp Blizzard

6129/tcp Dameware Software conexión remota

6346/tcp Gnutella compartición de ficheros (Limewire, etc.)

6347/udp Gnutella

6348/udp Gnutella

6349/udp Gnutella

6350/udp Gnutella

6355/udp Gnutella

6667/tcp IRC IRCU Internet Relay Chat

6881/tcp BitTorrent puerto por defecto

6969/tcp BitTorrent puerto de tracker

7100/tcp Servidor de Fuentes X11

7100/udp Servidor de Fuentes X11

8000/tcp iRDMI por lo general, usado erróneamente en sustitución de 8080. También utilizado en el servidor de streaming ShoutCast.

8080/tcp HTTP HTTP-ALT ver puerto 80. Tomcat lo usa como puerto por defecto.

8118/tcp privoxy

9009/tcp Pichat peer-to-peer chat server

9898/tcp Gusano Dabber (troyano/virus)

10000/tcp Webmin (Administración remota web)

19226/tcp Panda SecurityPuerto de comunicaciones de Panda Agent.

12345/tcp NetBus en:NetBus (troyano/virus)

31337/tcp Back Orifice herramienta de administración remota (por lo general troyanos)

Page 31: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

31

LA INTERFACE SOCKET

Page 32: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

32

Introducción Los sockets son interfaces lógicos de entrada/salida que permiten la comunicación entre procesos que pueden residir en máquinas distintas pero que estén conectadas mediante una red. Es el mecanismo utilizado por las aplicaciones en red basadas en tecnología Internet, de ahí su importancia dada la difusión de ésta en la actualidad.

Las aplicaciones en red suelen responder a un modelo conocido como cliente-servidor. En este modelo, el servidor es un proceso encargado de la gestión de un determinado recurso de una máquina. El cliente, que, en general, se ejecuta en una máquina diferente, interacciona con el recurso remoto estableciendo una comunicación con el servidor, siguiendo las reglas impuestas por el protocolo de nivel de aplicación que corresponda.

Tras esta introducción a las comunicaciones en redes tipo Internet, pasamos a describir los interfaces de programación que permiten el acceso a los sockets en distintos lenguajes y sistemas operativos.

SOCKETS

Los sockets son interfaces lógicos que permiten la comunicación bidireccional entre procesos que se ejecutan en una misma máquina o en máquinas distintas conectadas en red. Por ejemplo, los navegadores web se comunican con los servidores web mediante sockets. Es frecuente encontrar en la bibliografía analogías entre sockets y teléfonos o buzones de correo. En cierto modo, estos últimos permiten la comunicación entre personas de forma similar a como los sockets hacen posible la interacción entre procesos.

La comunicación mediante sockets es el mecanismo usado por la aplicaciones en red que se basan en tecnología Internet, es decir, en la familia de protocolos TCP/IP. De hecho, un socket no es más que la implementación del acceso a los servicios del nivel de transporte de la familia TCP/IP. En las aplicaciones en red es importante distinguir los recursos locales de los recusos remotos. Siguiendo con el ejemplo anterior, el navegador web prepara un socket local (es decir, en su máquina) para comunicarse con el socket remoto dispuesto por el servidor web. Por extensión, suele hablarse también de proceso local/remoto o incluso de máquina local/remota.

Identificación de un socket Desde el punto de vista de un proceso, un socket no es más que un recurso muy parecido a un fichero que se solicita localmente al sistema operativo y que, de alguna forma, “abre una puerta hacia el exterior”. Es fundamental que este socket esté identificado convenientemente para que pueda ser referenciado desde el exterior. La forma de identificar el socket está íntimamente relacionada con el mecanismo de direccionamiento de la familia de protocolos subyacente, es decir, la familia TCP/IP (Internet), y se describe a continuación.

Page 33: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

33

En la figura 1 se muestra la pila de protocolos de la familia TCP/IP, que puede asimilarse al modelo de referencia OSI si consideramos vacíos los niveles de sesión y presentación. Sobre una capa dependiente de la tecnología de red usada, encontramos el protocolo de nivel de red IP (Internet Protocol), responsable básicamente del direccionamiento de las estaciones y del enrutamiento de paquetes. Para nuestros propósitos, lo importante aquí es que, en la red, una máquina se distingue unívocamente de las demás mediante su dirección de nivel de red, llamada dirección IP. Sobre el nivel de red, cubriendo funciones propias del nivel de transporte, encontramos dos protocolos: TCP (Transmission Control Protocol) y UDP (User Datagram Protocol). TCP garantiza el transporte fiable de los datos, mientras que UDP no, pero presenta la ventaja de ser mucho más sencillo. Para nosotros, lo importante de estos protocolos de transporte es que incorporan un mecanismo de direccionamiento que permite diferenciar los sockets de una cierta máquina. Es decir, un socket que reside en una cierta máquina se distingue unívocamente de los demás sockets de la misma máquina mediante su dirección de nivel de transporte, habitualmente denominada puerto. Así, hablaremos de “puertos TCP” o “puertos UDP” dependiendo del protocolo de transporte que corresponda. En definitiva, el puerto nos permite distinguir los procesos relacionados con la red dentro de una misma máquina. Como consecuencia de todo lo anterior, un socket se identifica indicando la máquina en la que reside y el puerto al que está asociado, es decir:

socket: (dirección IP, puerto)

Las direcciones IP están formadas por 32 bits, es decir 4 bytes. Habitualmente se representan escribiendo el valor en decimal de cada byte (en el rango 0..255, por tanto), y separando los bytes con un punto, ‘.’. Por ejemplo supongamos, 150.214.180.50 es la dirección IP del servidor web de la Universidad de Ingenieria. Estas direcciones son asignadas por el administrador de la red. Existen direcciones IP especiales, como, por

Page 34: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

34

ejemplo, la dirección 127.0.0.1, cuya utilidad se explica a continuación. Toda máquina con capacidad de comunicaciones TCP/IP responde, al menos, a la dirección 127.0.0.1, aunque ni siquiera esté conectada a la red. Esto nos permite establecer comunicación entre procesos locales mediante sockets sin necesidad de que el equipo posea una dirección IP “real” (o bien, aunque la posea, no necesitamos conocerla para establecer comunicaciones locales). La dirección 127.0.0.1 nos permite comprobar el buen funcionamiento de la pila de protocolos.

Dado que la identificación de los equipos por su dirección IP es poco amigable, se desarrolló el servicio de nombres de dominio (DNS, Domain Name Service) que asocia la dirección IP de un host con un nombre de la forma host.dominio. Gracias a este sistema, podemos especificar en nuestro navegador la dirección www.etse.urv.es (host = www, dominio = etse.urv.es) para acceder al servidor web de la Universidad de Ingenieria, en lugar de introducir 150.214.180.50, por seguir con un ejemplo anterior. Análogamente, la dirección 127.0.0.1 equivale al nombre localhost.

Los puertos son valores de 16 bits, y por tanto cubren el rango 0..65535. Algunos de estos puertos están asignados para las aplicaciones estándar de Internet1. Por ejemplo, el puerto 80 es el puerto estándar en el que un servidor web recibe las solicitudes del navegador. El resto de los puertos pueden ser usados libremente por las aplicaciones, aunque normalmente los sistemas operativos se reservan un conjunto de puertos para uso interno. Siguiendo con un ejemplo anterior, el servidor web de la Universidad de Ingenieria recibe peticiones desde los clientes a través del socket identificado por (dir. IP = 150.214.180.50, Puerto = 80).

Tipos de sockets Como hemos visto, los sockets están relacionados íntimamente con el protocolo de transporte. En la familia TCP/IP tenemos dos posibles protocolos de transporte, TCP y UDP, por lo que, en consecuencia, existen dos tipos de sockets2:

Sockets TCP, “stream” u “orientados a la conexión”.

La comunicación entre sockets TCP es fiable (sin pérdida de paquetes), ordenada (TCP nos proporciona los paquetes en la secuencia correcta) y sin duplicación de paquetes. TCP, y consecuentemente, este tipo de sockets, es orientado a la conexión. Esto quiere decir que los sockets de los extremos a comunicar deben establecer un circuito virtual a través del cual se producirá el intercambio de información. El establecimiento del circuito virtual se suele denominar conexión, y es el paso previo al intercambio de datos. Una vez finalizado éste, se procede

1 Esta asignación de puertos puede encontrarse en el documento RFC1700. Las RFCs (Request for Comment) son documentos oficiales del IETF (Internet Engineering Task Force), que recogen los estándares, borradores de estándar y recomendaciones sobre todos los aspectos de Internet. 2 A veces es posible usar, además de los tipos de sockets descritos, un tipo especial denominado "raw", a través del cual se tiene acceso directamente al protocolo IP, dejando vacío el nivel de transporte.

Page 35: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

35

la desconexión. En la analogía que señalábamos al principio del apartado 2, los sockets TCP se parecen más a los teléfonos, en los cuales la conexión se corresponde con la realización de una llamada. El destino es seleccionado gracias a su número de telefóno y avisado mediante los tonos apropiados. Cuando el destino descuelga, se establece el circuito virtual y es posible la comunicación bidireccional. Cuando ésta termina, los dos extremos cuelgan, cerrando el circuito.

Sockets UDP, “datagram” o “no orientados a la conexión”.

La comunicación entre sockets UDP no garantiza la llegada de todos los paquetes, ni su orden, ni su unicidad. La aplicación que use sockets de este tipo tendrá que encargarse de resolver estos problemas potenciales. Para la comunicación entre sockets UDP no se establece un circuito virtual, sino que en su lugar se realiza un intercambio de datagramas, es decir, de paquetes sueltos. Siguiendo con la analogía anterior, los sockets UDP se parecen más a los buzones de correo. El emisor sólo se encarga de introducir la información en el buzón. El servicio de correos, que representa a la red de comunicaciones, transporta la información hasta el destino, introduciéndola en su buzón. En ningún momento ha existido un contacto directo entre los extremos. De hecho, el emisor ni siquiera tiene la certeza de que el destino exista (en cuyo caso la información se pierde; en la comunicación entre sockets UDP no hay el equivalente postal a la devolución al remitente).

A partir de este punto, nos ocuparemos únicamente de los sockets TCP.

Modelo de comunicación cliente-servidor Las aplicaciones en red basadas en sockets TCP suelen presentar la arquitectura cliente-servidor. En este modelo, existen los procesos a comunicar pueden presentar los siguientes roles:

- Servidor. Se trata de un proceso que gestiona el acceso a algún tipo de recurso, por ejemplo, páginas web o una base de datos. El servidor es, por tanto, un proceso ininterrumpido, ya que sin él, el recurso no estaría disponible para las aplicaciones en red que lo necesiten.

- Cliente. Es un proceso que necesita acceder al recurso remoto gestionado por el servidor, de forma que tendrá que comunicarse con éste para llevar a cabo su tarea.

Hay que tener en cuenta que un mismo proceso puede presentar un rol de servidor respecto de otro proceso, pero al mismo tiempo también rol de cliente desde el punto de vista de un tercer proceso.

Page 36: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

36

Proceso de conexión cliente-servidor El proceso de conexión entre cliente y servidor se ha representado en la figura 2, y se describe a continuación.

1- El proceso servidor, en su arranque, reserva un socket, s, denominado socket servidor, en su máquina local, y se queda en estado de espera, figura 2a.

2- El socket servidor (dirección IP y número de puerto) es conocido por el cliente, de forma que, cuando éste necesita acceder al recurso gestionado por el servidor, crea un socket, c, denominado socket cliente, y envía una solicitud de conexión al socket servidor, figura 2b.

3- El proceso servidor, que recibe la solicitud del cliente a través del socket servidor, crea un nuevo socket, s’, que se encargará de la comunicación con el cliente que ha solicitado la conexión, y lo conecta al socket cliente, figura 2c. El nuevo socket hereda la dirección del socket servidor (dirección IP y puerto)3. El socket servidor vuelve a su estado de escucha, lo que permite que se puedan aceptar nuevas solicitudes desde otros clientes de forma concurrente.

Normalmente, los servidores son multihilo4, para poder soportar esta forma de trabajo; así, cuando se crea un socket en el servidor para interactuar con un determinado cliente, se crea también un nuevo proceso servidor, que se encargará de atender las solicitudes de dicho cliente.

Una vez establecida la comunicación, es posible el intercambio de información. Dado que son sockets de tipo TCP, se tiene garantía de que todos los datos llegarán, y además, en el orden correcto, y sin duplicados.

4- Cuando el intercambio de información termina, el proceso cliente y el proceso que atiende a éste en el servidor cierran sus respectivos sockets, finalizando así la conexión. Por tanto, volvemos al estado inicial, figura 2.

3 El socket que se ha creado en la máquina servidora para llevar a cabo la comunicación con el cliente tiene características similares al socket cliente, esto es, no está en estado de escucha, sino preparado para enviar y recibir información. 4 Esto es, que tienen varios procesos ejecutándose concurrentemente en la máquina.

Page 37: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

37

Page 38: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

38

Modelo de programación El proceso de conexión descrito en el apartado anterior, desde el punto de vista del programador de procesos servidores o clientes, se corresponde con el diagrama mostrado en la figura 3.

Page 39: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

39

Las acciones que aparecen en el diagrama se explican a continuación. El proceso servidor crea (“abre”) el socket servidor(socket), le asigna un puerto (bind) en la máquina servidora y lo prepara para la escucha (listen), asignándole una cola de conexiones pendientes de procesar. A partir de este momento, el socket pasa a estado de espera de conexión por parte del cliente (accept).

El cliente, por su parte, crea un socket de usuario (socket) y trata de conectarlo al socket

Servidor (connect), para establecer la comunicación.

Cuando el proceso servidor recibe tal solicitud, éste crea un proceso hijo para que se encargue de la comunicación con el cliente. También crea un socket (accept) y se lo asigna al nuevo proceso. El proceso servidor vuelve a su estado de espera de conexión (accept).

El proceso cliente y el proceso hijo del servidor intercambian información (send, recv). Normalmente, aunque no es obligatoriamente así, el cliente es el primero que envía información (tal como aparece en la figura 3). Cuando la comunicación termina, ambos “cierran” sus respectivos sockets (close).

Las acciones socket, bind, listen, accept, connect, send, recv y close se corresponden uno a uno con las funciones del API en lenguaje C del sistema UNIX para el manejo de sockets. Independientemente de la variante de UNIX que consideremos, el API es el mismo, ya que todas ellas siguen las especificaciones del estándar POSIX. Windows también sigue este enfoque y proporciona un API muy similar al de UNIX aunque con algunas modificaciones y extensiones. El apartado 4.1 trata con cierto detalle el API de UNIX (según el estándar POSIX) para la manipulación de sockets; dada la semejanza con su equivalente en Windows, el apartado 4.2 se limita a mostrar las diferencias entre ellos. Éste incluye también una breve referencia acerca de las clases disponibles para la programación de sockets bajo C++ usando las MFC (Microsoft Foundation Classes). Por último, el apartado 4.3 hace una breve introducción a la programación de sockets en Java, lenguaje muy extendido actualmente con soporte multiplataforma, lo cual lo hace muy interesante ya que un programa escrito en Java funcionará en Windows, Linux, Solaris, HP-UX, etc.sin necesidad de recompilación.

Byte order El flujo de datos entre sockets TCP está orientado al intercambio de bytes (char en lenguaje C). Supongamos que queremos una secuencia de words (short en C) o double words (long en C), compuestos por 2 y 4 bytes respectivamente. ¿En qué orden debemos enviar los bytes individuales que componen cada uno de estos datos? Sistemas basados en microprocesadores distintos usan diferentes convenciones a la hora de almacenar internamente estos tipos de datos, como es el caso de los Intel x86 (primero el byte menos significativo, convención little endian) y Motorola 680xx (primero el byte más significativo, convención big endian).

Para solucionar el problema, se distinguen dos tipos de ordenamiento: el host order (el

Page 40: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

40

orden con el que se almacena en el equipo, que será little o big endian dependiendo del sistema) y el network order (el orden establecido por convención para las redes tipo Internet, concretamente big endian), y se establecen las siguientes reglas:

· todos los datos que se envíen hacia la red deben convertirse al network order.

· todos los datos que se reciban de la red deben convertirse al host order.

De esta forma, si el extremo A quiere transmitir un dato (de longitud mayor a un byte) al extremo B, lo primero que hace es convertir el dato desde el host order de A al network order. El dato, una vez recibido en B en network order, se transforma al host order de B. De esta forma, independientemente de cuáles sean los host order de A y B, la comunicación se realiza correctamente. La clave está en que se ha definido un network order universal, que siempre se respeta.

Insistimos en que el problema de orden de envío es relevante sólo cuando la unidad de información tiene una longitud superior a un byte.

Las funciones short htons(short) y long htonl(long) realizan la conversión de

host order a network order de un entero tipo short o long, respectivamente, mientras que short ntohs(short) y long ntohl(long) realizan las conversiones opuestas, es decir, de network order a host order. Estas funciones están definidas en el fichero de cabecera

<netinet/in.h>.

Programación de sockets en Windows Bajo Windows, las operaciones de sockets son competencia de la librería dinámica winsock2 (Windows Sockets Version 2). Básicamente, el API winsock2 consta de las funciones estilo POSIX descritas en el apartado anterior, aunque incluyendo algunas modificaciones, y de un conjunto de funciones propias, que, por convención, están precedidas por el prefijo WSA-. Tan sólo trataremos con las más fundamentales de estas funciones añadidas tipo WSA-. A continuación se enumeran los aspectos propios de Windows en cuanto a la programación de sockets:

Para poder usar las funciones de sockets en Windows, hay que incluir el fichero de cabecera <winsock2.h> en lugar de <sys/socket.h>, <sys/types.h> y <netinet/in.h>.

Es necesario añadir al enlazador (linker) la librería estática ws2_32.lib. En Microsoft Visual C++ 6.0, esto se hace incluyéndola en Project > Settings > Link > Object/Library Modules.

Los descriptores de sockets, que en POSIX son tipo int, aquí son de tipo SOCKET. Por ejemplo, el prototipo de la función listen() pasa a ser int listen(SOCKET s, int backlog); análogamente con el resto de funciones.

Las funciones que devuelven un descriptor de socket utilizan ahora la constante INVALID_SOCKET para indicar un error (en lugar de devolver -1).

Page 41: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

41

El resto de funciones que manejan sockets (que devuelven int) indican una situación de error mediante la constante SOCKET_ERROR (en lugar de devolver -1). Es el caso, por ejemplo, de send() y recv().

La función close() en winsock2 se denomina closesocket(), aunque manteniendo la misma signatura.

En winsock2, la variable errno no es actualizada con el error producido. En su lugar, hay que invocar a WSAGetLastError() para obtener el código de error.

Antes de realizar cualquier llamada a winsock2 es necesario invocar la función WSAStartup(), que se encarga de iniciar esta librería. Análogamente, cuando ya no sea necesario seguir usando winsock2, debe llamarse a WSACleanup(). Típicamente, el código necesario para llamar a WSAStartup() es de la forma:

WORD wVersionRequested;

WSADATA wsaData;

wVersionRequested = MAKEWORD(2, 2);

if(WSAStartup(wVersionRequested, &wsaData) != 0) {

printf("Error: WSAStartup\n");

exit(1);

}

Mientras que para WSACleanup():

if(WSACleanup() == SOCKET_ERROR) {

printf("Error: WSACleanup\n");

exit(1);

}

Para más información sobre la programación de sockets en Windows, puede consultarse la MSDN Library Visual Studio, en Platform SDK > Networking and Distributed Services > Windows Sockets Version 2 API.

Programación de sockets en Windows usando C++ y MFC Microsoft ha desarrollado un conjunto de clases C++ que encapsulan prácticamente todo en API de Windows, incluyendo las funciones de manejo de sockets; son las clases base de Microsoft o MFC (Microsoft Foundation Classes). Por lo tanto, es una alternativa a considerar especialmente si estamos desarrollando una aplicación con un enfoque orientado a objetos para Windows. En MFC, se definen dos clases relacionadas con sockets:

Page 42: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

42

CAsyncSocket. Encapsula las funciones descritas en el apartado anterior, facilitando además la posibilidad de realizar programación orientada a eventos, de forma que se pueden definir funciones de callback que son notificadas cuando se ha recibido información, cuando el socket está libre para seguir enviando, etc.

CSocket. Deriva de la anterior. Proporciona un interfaz con un mayor nivel de abstracción, evitando detalles que sí aparecen en CAsyncSocket. En particular, las funciones de Csocket incorporan bloqueo.

Para más información, consultar la MSDN Library Visual Studio.

Page 43: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

43

Fundamentos sobre el control MSWinsockControl

Page 44: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

44

El MSWinsockControl incluido con Visual C++ es una herramienta muy poderosa para la creación de aplicaciones basadas en sockets.

Con MSWinsockControl se pueden implementar los diferentes protocolos utilizados en

Internet e inclusive protocolos propios.

Los principales protocolos de Internet basados en TCP/IP son:

HTTP Hypertext Transfer Protocol (páginas Web) puerto 80

FTP File Transfer Protocol (transferencia de ficheros) puerto 21

SMTP Simple Mail Transfer Protocol (envío de email) puerto 25

POP3 Post Office Protocol (recepción email) puerto 110

NNTP Network News Transfer Protocol (noticias) puerto 119

Las aplicaciones que se han desarrollado pueden utilizar tantos sockets como sean necesarios para realizar la tarea encomendada de la manera más eficiente pero siempre teniendo en cuenta que cada socket trabaja sobre un único puerto.

El control WinSock permite conectarse a un equipo remoto e intercambiar datos con el Protocolo de datagramas de usuario (UDP) o con el Protocolo de control de transmisión (TCP). Ambos protocolos se pueden usar para crear aplicaciones cliente-servidor. Al igual que el control Timer, el control WinSock no tiene una interfaz visible en tiempo de ejecución.

Aplicaciones posibles

- Crear una aplicación cliente que recopile información del usuario antes de enviarla a un servidor central.

- Crear una aplicación servidora que funcione como un punto central de recopilación de datos procedentes de varios usuarios.

- Crear una aplicación de "conversación".

Seleccionar un protocolo

Cuando se utiliza el control WinSock, primero debe tener en cuenta es si se va a usar el protocolo TCP o el protocolo UDP. La principal diferencia entre los dos radica en su estado de conexión:

TCP es un protocolo basado en la conexión y es análogo a un teléfono: el usuario debe establecer una conexión antes de continuar.

UDP es un protocolo sin conexión y la transacción entre los dos equipos es como

Page 45: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

45

pasar una nota: se envía un mensaje desde un equipo a otro, pero no existe una conexión explícita entre ambos. Además, el tamaño máximo de los datos en envíos individuales está determinado por la red.

La naturaleza de la aplicación que se esté creando determinará generalmente qué protocolo se debe seleccionar. He aquí varias cuestiones que pueden ayudar a seleccionar el protocolo adecuado:

1- ¿Necesita la aplicación la confirmación por parte del cliente o el servidor cuando se envíen o reciban datos? Si es así, el protocolo TCP requiere una conexión explícita antes de enviar o recibir datos.

2- ¿Será muy grande el tamaño de los datos (como en el caso de los archivos de imágenes o sonidos)? Una vez establecida la conexión, el protocolo TCP mantiene la conexión y asegura la integridad de los datos. No obstante, esta conexión utiliza más recursos del sistema, por lo que resulta más "cara".

3- ¿Se envian los datos de forma intermitente o en una sesión? Por ejemplo, si se está creando una aplicación que avisa a equipos específicos cuando se han completado ciertas tareas, el protocolo UDP puede ser el más apropiado. Este protocolo es también el más adecuado para enviar pequeñas cantidades de datos.

Establecer el protocolo

Para establecer el protocolo que la aplicación va a usar: en tiempo de diseño, en la ventana Propiedades, Se entra en Protocolo y se selecciona sckTCPProtocol o sckUDPProtocol. También se puede establecer la propiedad Protocol en el código, como se muestra a continuación:

Código:

Winsock1.Protocol = sckTCPProtocol

Determinar el nombre del equipo

Para conectarse a un equipo remoto, se deberá saber su dirección IP o su "nombre descriptivo". La dirección IP está formada por un conjunto de tres dígitos separados por puntos (xxx.xxx.xxx.xxx). En general, es mucho más fácil recordar el nombre descriptivo de un equipo.

Para encontrar el nombre del equipo:

1- En la Barra de tareas del equipo, se hace clic en Inicio.

2- En el elemento Configuración, se hace clic en Panel de control.

3- Se hace doble clic en el icono Red.

4- Se hace en la ficha Identificación.

Page 46: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

46

5- El nombre del equipo aparecerá en el cuadro Nombre del equipo.

Después de encontrar el nombre del equipo, se puede usar como el valor de la propiedad RemoteHost.

Conceptos básicos de conexión con el protocolo TCP

Cuando se crea una aplicación que utilice el protocolo TCP, deberá decidir primero si la aplicación va a ser un servidor o un cliente. Si crea un servidor, la aplicación va a "escuchar" en el puerto designado. Cuando el cliente realice una solicitud de conexión, el servidor puede aceptar la solicitud y completar así la conexión. Una vez realizada la conexión, el cliente y el servidor se podrán comunicar entre sí sin problemas.

Aceptar más de una solicitud de conexión

Un servidor básico sólo acepta una solicitud de conexión. No obstante, es posible aceptar varias solicitudes de conexión con el mismo control si crea una matriz de controles. En este caso, no necesita cerrar la conexión; basta con crear una nueva instancia del control (estableciendo la propiedad Index) e invocar el método Accept de la nueva instancia.

Conceptos básicos del protocolo UDP

Crear una aplicación UDP es todavía más sencillo que crear una aplicación TCP, ya que el protocolo UDP no requiere una conexión explícita. En la aplicación TCP anterior hubo que establecer explícitamente un control Winsock para "escuchar", mientras que el otro debía iniciar la conexión con el método Connect. En cambio, el protocolo UDP no requiere una conexión explícita. Para enviar datos entre los dos controles, se deben completar tres pasos (en ambos lados de la conexión):

1- Establecer la propiedad RemoteHost con el nombre del otro equipo.

2- Establecer la propiedad RemotePort con la propiedad LocalPort del segundo control.

3- 3. Invocar el método Bind especificando la propiedad LocalPort que se va a usar. (Este método se trata detenidamente más adelante.)

Acerca del método Bind

Este método "reserva" un puerto local para uso del control. Por ejemplo, al enlazar el control al número de puerto 1001, ninguna otra aplicación podrá usar ese puerto para "escuchar". Esto puede ser muy útil si desea impedir que otra aplicación utilice ese puerto.

Page 47: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

47

El método Bind también ofrece un segundo argumento opcional. Si hay más de un adaptador de red presente en el equipo, el argumento IPlocal permite especificar qué adaptador usar. Si se omite este argumento, el control usará el primer adaptador de red que aparece en la lista del cuadro de diálogo Red de la opción Configuración del Panel de control.

Si utiliza el protocolo UDP, se puede cambiar libremente las propiedades RemoteHost y RemotePort mientras permanezca conectado al mismo puerto local. No obstante, con el protocolo TCP deberá cerrar la conexión antes de cambiar las propiedades RemoteHost y RemotePort.

Winsock (Control)

El control Winsock, invisible para el usuario, proporciona un acceso sencillo a los servicios de red TCP y UDP. Pueden usarlo los programadores de Microsoft Access, Visual Basic, Visual C++ o Visual FoxPro. Para escribir aplicaciones de servidor o de cliente no necesita comprender los detalles de TCP ni llamar a las API de Winsock de nivel inferior. Si establece las propiedades y llama a los métodos del control, podrá conectar fácilmente con un equipo remoto e intercambiar datos en las dos direcciones.

Conceptos básicos de TCP

El Protocolo de control de transferencia (TCP) permite crear y mantener una conexión con un equipo remoto. Mediante la conexión, ambos equipos pueden intercambiar datos entre sí. Si se está creando una aplicación de cliente, se debe saber el nombre del equipo servidor o su dirección IP (propiedad RemoteHost), así como el puerto (propiedad RemotePort) en el que se está "escuchando". Después, llamar al método Connect.

Si se está creando una aplicación de servidor, se debe establecer el puerto (propiedad LocalPort) en el que escuchar y llamar al método Listen. Cuando el equipo cliente solicite una conexión, se producirá el evento ConnectionRequest. Para completar la conexión, llamar al método Accept del evento ConnectionRequest.

Una vez establecida la conexión, los equipos pueden enviar y recibir datos. Para enviar datos, se debe llamar al método SendData. Siempre que se reciben datos, se produce el evento DataArrival. Llamar al método GetData del evento DataArrival para recuperar los datos.

Conceptos básicos de UDP

El Protocolo de datagramas de usuarios (UDP) es un protocolo sin conexiones. A diferencia de las operaciones de TCP, los equipos no establecen una conexión. Asimismo, una aplicación UDP puede ser cliente o servidor.

Para transmitir datos, establecer primero la propiedad LocalPort del equipo cliente. El

Page 48: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

48

equipo servidor sólo necesita establecer RemoteHost a la dirección de Internet del equipo cliente y la propiedad RemotePort al mismo puerto que la propiedad LocalPort del equipo cliente, y llamar al método SendData para comenzar a enviar mensajes. Después, el equipo cliente utiliza el método GetData del evento DataArrival para recuperar los mensajes enviados.

Propiedades Winsock(control)

BytesReceived (Propiedad)

Devuelve la cantidad de datos recibidos (que están actualmente en el búfer de recepción). Utilice el método GetData para recuperar los datos.

Es de sólo lectura y no está disponible en tiempo de diseño.

- Sintaxis: objeto.BytesReceived

- Valor devuelto: Long

LocalHostName (Propiedad)

Devuelve el nombre de la máquina local. Es de sólo lectura y no está disponible en tiempo de diseño.

- Sintaxis: objeto.LocalHostName

- Valor devuelto:String

LocalIP (Propiedad)

Devuelve la dirección IP de la máquina local en el formato de cadena con puntos de dirección IP (xxx.xxx.xxx.xxx). Es de sólo lectura y no está disponible en tiempo de diseño. - Sintaxis: objeto.LocalIP

Tipo de datos: String

LocalPort (Propiedad)

Devuelve o establece el puerto local que desea usar. Es de lectura y escritura, y está disponible en tiempo de diseño.

En el cliente, designa el puerto local desde el que desea enviar los datos. Especifique el puerto 0 si la aplicación no necesita un puerto específico. En este caso, el control seleccionará un puerto de forma aleatoria. Una vez establecida la conexión, éste es el puerto local utilizado para la conexión TCP.

En el servidor, es el puerto local en el que se escuchará. Si especifica el puerto 0,

Page 49: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

49

se utiliza un puerto seleccionado de forma aleatoria. Después de llamar al método Listen, la propiedad contiene el puerto actual seleccionado.

- Sintaxis: objeto.LocalPort = largo

- Tipo de datos: Long

Comentarios Para establecer dinámicamente conexiones entre dos equipos, se suele usar el puerto 0. Por ejemplo, un cliente que desea que un servidor le "devuelva la llamada" puede usar el puerto 0 para obtener un nuevo número de puerto (aleatorio), que pueda proporcionar al equipo remoto para ese propósito.

Protocol (Propiedad, control Winsock)

Devuelve o establece el protocolo, TCP o UDP, utilizado por el control Winsock.

- Sintaxis: objeto.Protocol [=protocolo]

- Valores. Los valores de protocolo son:

Código:

Constante Valor Descripción sckTCPProtocol 0 Predeterminado. Protocolo TCP. sckUDPProtocol 1 Protocolo UDP.

- Valor devuelto: Ninguno

Comentarios Debe cerrar el control (con el método Close) antes de que se pueda restablecer esta propiedad.

RemoteHostIP (Propiedad)

Devuelve la dirección IP del equipo remoto.

En las aplicaciones de cliente, después de establecer la conexión con el método Connect, esta propiedad contiene la cadena IP del equipo remoto.

En las aplicaciones de servidor, después de la llegada de una solicitud de llamada (evento ConnectionRequest), esta propiedad contiene la cadena IP del equipo remoto que inició la conexión.

Cuando utiliza el protocolo UDP, después de producirse el evento DataArrival, esta propiedad contiene la dirección IP del equipo que envía los datos UDP.

- Sintaxis: objeto.RemoteHostIP

- Tipo de datos: String

Page 50: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

50

SocketHandle (Propiedad) Devuelve un valor que corresponde al controlador de socket que utiliza el control para comunicarse con la capa Winsock. Es de sólo lectura y no está disponible en tiempo de diseño.

- Sintaxis: objeto.SocketHandle

- Tipo de datos: Long

Comentarios Esta propiedad se diseñó para pasarla a las API de Winsock. State (Propiedad, control Winsock) Devuelve el estado del control, expresado como un tipo enumerado. Es de sólo lectura y no está disponible en tiempo de diseño.

- Sintaxis: objeto.State

- Tipo de datos: Integer

- Valores. Los valores de la propiedad State son:

Código:

Constante Valor Descripción sckClosed 0 Predeterminado. Cerrado sckOpen 1 Abierto sckListening 2 Escuchando sckConnectionPending 3 Conexión pendiente sckResolvingHost 4 Resolviendo host sckHostResolved 5 Host resuelto sckConnecting 6 Conectando sckConnected 7 Conectado sckClosing 8 El equipo está cerrando la conexión sckError 9 Error

Index (Propiedad, controles ActiveX)

Establece o devuelve el número que identifica inequívocamente un objeto de una colección. - Sintaxis: objeto.Index

Comentarios La propiedad Index se establece de forma predeterminada al orden de creación de los objetos en una colección. El índice para el primer objeto de una colección será siempre uno (1).

El valor de la propiedad Index de un objeto puede cambiar cuando se ordenan de nuevo los objetos de la colección, como cuando establece la propiedad Sorted a True. Si espera que la propiedad Index cambie dinámicamente, puede que sea más útil hacer referencia a los objetos de una colección mediante la propiedad Key.

Page 51: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

51

Name (Propiedad)

Devuelve el nombre utilizado en el código para identificar un formulario, un control o un objeto de acceso a datos. Es de sólo lectura en tiempo de ejecución.

Devuelve o establece el nombre de un objeto fuente.

- Sintaxis: objeto.Name

Object (Propiedad, controles ActiveX)

Devuelve el objeto y un valor de un método o propiedad de un objeto. - Sintaxis: objeto.Object[.propiedad | .método]

La sintaxis de la propiedad Object consta de las siguientes partes:

Código:

Parte Descripción objeto Una expresión de objeto que da como resultado un objeto de la lista Se aplica a. propiedad Propiedad compatible con el objeto. método Método compatible con el objeto.

Comentarios Utilizar esta propiedad para especificar un objeto que desea usar en una tarea de Automatización.

Para usar en una tarea de Automatización el objeto devuelto por la propiedad Object, utilizar las propiedades y los métodos de dicho objeto. Para obtener información acerca de las propiedades y los métodos compatibles con un objeto, ver la documentación de la aplicación que creó el objeto.

Parent (Propiedad)

Devuelve el formulario, objeto o colección que contiene un control u otro objeto o colección. - Sintaxis: objeto.Parent

Comentarios Utilizar la propiedad Parent para tener acceso a las propiedades, los métodos o los controles del primario de un objeto.

La propiedad Parent es útil en una aplicación en la que se pasan objetos como argumentos. Por ejemplo, se podría pasar una variable de control a un procedimiento general en un módulo y usar la propiedad Parent para tener acceso a su formulario primario. RemoteHost (Propiedad, controles ActiveX)

Page 52: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

52

Devuelve o establece el equipo remoto al que un control envía datos, o aquél del que los recibe. Puede indicar el nombre de host, como "FTP://ftp.microsoft.com" o como una cadena de dirección IP en el formato con puntos, como "100.0.1.1".

- Sintaxis: objeto.RemoteHost = cadena

La sintaxis de la propiedad RemoteHost consta de las siguientes partes:

Código:

Parte Descripción objeto Una expresión de objeto que da como resultado un objeto de la lista Se aplica a. cadena El nombre o la dirección del equipo remoto.

Comentarios Cuando se especifica esta propiedad, la propiedad URL se actualiza para mostrar el nuevo valor. Además, si se actualiza la parte de host de la dirección URL, esta propiedad también se modifica para reflejar el nuevo valor.

La propiedad RemoteHost también puede modificarse al invocar los métodos OpenURL o Execute. En tiempo de ejecución, el cambio de este valor no tiene ningún efecto hasta la conexión siguiente.

RemotePort (Propiedad, controles ActiveX)

Devuelve o establece el número del puerto remoto con el que conectar.

- Sintaxis: objeto.RemotePort = puerto

La sintaxis de la propiedad RemotePort consta de la siguientes partes:

Código:

Parte Descripción objeto Control Winsock puerto El puerto con el que conectar. El valor predeterminado de esta propiedad es 80.

Tipo de dato Integer

Comentarios Al establecer la propiedad Protocol, en la propiedad RemotePort se establece automáticamente el puerto predeterminado correspondiente a cada protocolo. Los números de puerto predeterminados se muestran en la siguiente tabla:

Código:

Puerto Descripción 80 HTTP, utilizado habitualmente para las conexiones con el World Wide Web. 21 FTP.

Tag (Propiedad, controles ActiveX)

Page 53: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

53

Devuelve o establece una expresión que almacena cualquier dato adicional necesario para su programa.

- Sintaxis: objeto.Tag [= expresión]

La sintaxis de la propiedad Tag consta de las siguientes partes:

Código:

Parte Descripción objeto Casi cualquier objeto expresión Cualquier texto

Winsock(Metodos) Accept (Método)

Sólo para las aplicaciones de servidor TCP. Este método se utiliza para aceptar una conexión entrante cuando se está tratando un evento ConnectionRequest.

- Sintaxis: objeto.Accept IdSolicitud

- Tipo de datos: Long

- Valor devuelto: Ninguno

Comentarios El método Accept se utiliza en el evento ConnectionRequest. El evento ConnectionRequest tiene un argumento, el parámetro RequestID, que debe pasarse al método Accept.

Debe usar el método Accept en una nueva instancia del control (distinta de la que está en estado de escucha.)

Bind (Método)

Especifica el puerto local y la dirección IP local a usar en las conexiones TCP. Utilice este método si tiene múltiples adaptadores de protocolo.

- Sintaxis: objeto.Bind puertoLocal, IPLocal

La sintaxis del método Bind consta de las siguientes partes:

Código:

Parte Descripción objeto Control Winsock puertoLocal Puerto utilizado para realizar una conexión. IPLocal Dirección local de Internet utilizada para realizar una conexión.

Comentarios Debe llamar al método Bind antes de llamar al método Listen. Close (Método, control Winsock)

Page 54: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

54

Cierra una conexión TCP o un socket en escucha para las aplicaciones de cliente y de servidor.

- Sintaxis: objeto.Close

- Argumentos: Ninguno

- Valor devuelto: Ninguno

GetData (Método, control Winsock) Recupera el bloque actual de datos y lo almacena en una variable de tipo Variant.

- Valor devuelto: Ninguno

- Sintaxis: objeto.GetData datos, [tipo,] [longMáx]

La sintaxis del método GetData consta de las siguientes partes:

Código:

Parte Descripción objeto Control Winsock datos Dónde se almacenarán los datos recuperados después de que el método termine

correctamente. Si no hay suficientes datos disponibles para el tipo requerido, datos

se establecerá a Vacío. tipo Opcional. Tipo de datos a recuperar, como se muestra en Valores. longMáx Opcional. Especifica el tamaño deseado cuando se recibe una matriz de bytes o

una cadena. Si se omite este parámetro para las matrices de bytes o las cadenas, se

recuperarán todos los datos disponibles. Si se proporciona para tipos de datos que

no sean matrices de bytes o cadenas, se pasa por alto el parámetro.

Valores Los valores de tipo son:

Código:

Descripción Constante Byte VbByte Entero VbInteger Largo VbLong Simple VbSingle Doble vbDouble Moneda vbCurrency Fecha vbDate Booleano vbBoolean SCODE vbError Cadena vbString Matriz de bytes vbArray + vbByte

Comentarios

Page 55: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

55

El método GetData se suele usar con el evento DataArrival, que incluye el argumento bytesTotales. Si especifica una longMáx menor que el argumento bytesTotales, obtendrá el mensaje de advertencia 10040, que indica que se perderán los bytes restantes. Listen (Método)

Crea un socket y lo establece a modo de escucha. Este método sólo funciona en las conexiones TCP.

- Sintaxis: objeto.Listen

- Argumentos: Ninguno

- Valor devuelto: Ninguno

Comentarios El evento ConnectionRequest se produce cuando hay una conexión entrante. Cuando se está tratando un evento ConnectionRequest, la aplicación debería usar el método Accept (en una nueva instancia del control) para aceptar la conexión.

PeekData (Método)

Similar a GetData, excepto que PeekData no elimina los datos de la cola de entrada. Este método sólo funciona en las conexiones TCP.

- Sintaxis: objeto.PeekData datos, [tipo,] [longMáx]

La sintaxis del método PeekData consta de las siguientes partes:

Código:

Parte Descripción objeto Control Winsock datos Almacena los datos recuperados después de que el método acaba

satisfactoriamente. Si no hay suficientes datos disponibles para el tipo solicitado,

datos se establecerá a Vacío. tipo Opcional. Tipo de los datos a recuperar, como se describe en Valores. Valor

predeterminado: vbArray + vbByte. longMáx Opcional. Longitud que especifica el tamaño deseado cuando se recibe una matriz

de bytes o una cadena. Si falta este argumento para las matrices de bytes o

cadenas, se recuperan todos los datos disponibles. Si se proporciona para otros

tipos de datos que no sean matrices de bytes o cadenas, se pasa por alto el

argumento.

Valores Los valores de tipo son:

Código:

Page 56: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

56

Tipo Constante Byte VbByte Entero VbInteger Largo VbLong Simple VbSingle Doble VbDouble Moneda vbCurrency Fecha VbDate Booleano VbBoolean SCODE VbError Cadena VbString Matriz de bytes VbArray + vbByte

- Valor devuelto: Ninguno

Comentarios Si el tipo se especifica como vbString, la cadena de datos se convierte a UNICODE antes de devolverla al usuario.

SendData (Método)

Envía datos a un equipo remoto.

- Valor devuelto: Ninguno

- Sintaxis: objeto.SendData datos

La sintaxis del método SendData consta de las siguientes partes:

Código:

Parte Descripción objeto Control Winsock datos Datos que desea enviar. Para los datos binarios, debería usar matrices de datos.

Comentarios Cuando pasa una cadena UNICODE, se convierte a cadena ANSI antes de enviarla a la red. Winsock(eventos) Close (Evento)

Se produce cuando el equipo remoto cierra la conexión. Las aplicaciones deben usar el método Close para cerrar correctamente una conexión TCP.

- Sintaxis: objeto_Close( )

- Argumentos: Ninguno

Page 57: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

57

Connect (Evento, control Winsock)

Ocurre cuando se ha completado una operación de conexión.

- Sintaxis: objeto.Connect()

Comentarios Usar el evento Connect para confirmar que se ha realizado con éxito la conexión ConnectionRequest (Evento)

Se produce cuando el equipo remoto solicita una conexión. Sólo para aplicaciones de servidor TCP. El evento se activa cuando llega una solicitud de conexión. Las propiedades RemoteHostIP y RemotePort almacenan la información acerca del cliente después de que se ha activado el evento.

- Sintaxis: objeto_ConnectionRequest (IdSolicitud As Long)

La sintaxis del evento ConnectionRequest consta de las siguientes partes:

Código:

Parte Descripción objeto Control Winsock IdSolicitud Identificador de la solicitud de conexión entrante. Este argumento se debería

pasar al método Accept de la segunda instancia del control.

Comentarios El servidor puede decidir si acepta o no la conexión. Si no se acepta la conexión entrante, el equipo (cliente) obtendrá el evento Close. Utilice el método Accept (en una nueva instancia del control) para aceptar una conexión entrante.

DataArrival (Evento)

Se produce cuando llegan nuevos datos.

- Sintaxis: objeto_DataArrival (bytesTotales As Long)

La sintaxis del evento DataArrival consta de las siguientes partes:

Código:

Parte Descripción objeto Objeto Winsock bytesTotales Long. Cantidad total de datos que se puede recuperar.

Comentarios Este evento no se producirá si no recupera todos los datos con una llamada GetData. Sólo se activa cuando hay datos nuevos. Utilice la propiedad BytesReceived para comprobar la cantidad de datos disponibles en cualquier momento.

Page 58: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

58

Error (Evento, control Winsock Control)

Se produce siempre que ocurre un error en los procesos de segundo plano (por ejemplo, un fallo al conectar o un fallo al enviar o recibir en segundo plano).

- Sintaxis: objeto_Error(número As Integer, descripción As String, scode As Long, origen As String, archivoAyuda as String, contextoAyuda As Long, cancelarVista As Boolean)

- La sintaxis del evento Error consta de las siguientes partes:

Código:

Parte Descripción objeto Control Winsock número Entero que define el código de error. Vea las constantes más abajo, en Valores. descripción Cadena que contiene la información del error. scode SCODE largo. origen Cadena que describe el origen del error. archivoAyuda Cadena que contiene el nombre del archivo de ayuda. contextoAyuda Contexto del archivo de ayuda. cancelarVista Indica si se cancelará la vista del mensaje de error. El valor predeterminado es

False, que indica mostrar el cuadro de mensaje de error predeterminado. Si no

se desea usar el cuadro de mensaje predeterminado, establecer cancelarVista a

True.

Valores Los valores de número son:

Código:

Constante Valor Descripción sckOutOfMemory 7 Sin memoria sckInvalidPropertyValue 380 El valor de la propiedad no es válido. sckGetNotSupported 394 No se puede leer la propiedad. sckSetNotSupported 383 La propiedad es de sólo lectura. sckBadState 40006 Protocolo o estado de conexión incorrecto para la solicitud

o la transacción requerida. sckInvalidArg 40014 El argumento que se pasó a una función no estaba en el

formato correcto o en el intervalo especificado. sckSuccess 40017 Correcto. sckUnsupported 40018 Tipo Variant no aceptado. sckInvalidOp 40020 La operación no es válida en el estado actual. sckOutOfRange 40021 El argumento está fuera del intervalo. sckWrongProtocol 40026 Protocolo erróneo para la solicitud o la transacción

requerida. sckOpCanceled 10004 Se canceló la operación. sckInvalidArgument 10014 La dirección solicitada es una dirección de multidifusión,

pero el indicador no está activado. sckWouldBlock 10035 El socket es no bloqueante y la operación especificada se

Page 59: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

59

bloqueará. sckInProgress 10036 Se está efectuando una operación de Winsock bloqueante. sckAlreadyComplete 10037 Se completó la operación. No se están efectuando

operaciones bloqueantes. sckNotSocket 10038 El descriptor no es un socket. sckMsgTooBig 10040 El datagrama es demasiado grande para el búfer y se

truncará. sckPortNotSupported 10043 El puerto especificado no es compatible. sckAddressInUse 10048 Dirección en uso. sckAddressNotAvailable 10049 La dirección no está disponible en la máquina local. sckNetworkSubsystemFailed 10050 Error en el subsistema de red. sckNetworkUnreachable 10051 El host no puede encontrar la red en este momento. sckNetReset 10052 Expiró el tiempo de espera de la conexión antes de

establecer SO_KEEPALIVE. sckConnectAborted 10053 La conexión se ha cancelado al sobrepasar el tiempo de

espera o por otro error. sckConnectionReset 10054 La conexión se ha restablecido desde el lado remoto. sckNoBufferSpace 10055 No hay espacio disponible en el búfer. sckAlreadyConnected 10056 El socket ya está conectado.

sckNotConnected 10057 El socket no está conectado. sckSocketShutdown 10058 El socket se ha desactivado. sckTimedout 10060 Se ha sobrepasado el tiempo de conexión. sckConnectionRefused 10061 Se ha forzado el rechazo de la conexión. sckNotInitialized 10093 Es necesario llamar primero a WinsockInit. sckHostNotFound 11001 Respuesta autorizada: host no encontrado. sckHostNotFoundTryAgain 11002 Respuesta no autorizada: host no encontrado. sckNonRecoverableError 11003 Errores no recuperables. sckNoData 11004 Nombre válido; no hay registro de datos del tipo solicitado.

SendComplete (Evento)

Se produce cuando termina una operación de envío.

- Sintaxis: objeto_SendComplete

- Argumentos: Ninguno

SendProgress (Evento)

Se produce mientras se están enviando datos.

- Sintaxis: objeto_SendProgress (bytesEnv As Long, bytesRest As Long)

La sintaxis del evento SendProgress consta de las siguientes partes:

Código:

Parte Descripción objeto Expresión de objeto que da como resultado un objeto de la lista Se aplica a.

Page 60: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

60

bytesEnv Número de bytes enviados desde la última vez que se activó el evento. bytesRest Número de bytes que esperan en el búfer de envío a ser enviados.

Page 61: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

61

Diagramas de flujo

Page 62: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

62

Introducción A continuación se muestran los diagramas de flujo de cada una de las aplicaciones donde se puede observar el funcionamiento del programa.

Cada diagrama muestra el tratamiento de cada una de las excepciones que pueden ser invocadas en el programa, existen excepciones tratadas internamente desde el código y otras que son producidas por acontecimientos externos como la pulsación de un botón o el cambio producido en una ventana de texto del programa.

El primer diagrama de cada aplicación muestra el tratamiento a eventos producidos desde el menú de la aplicación, mientras que, los siguientes diagramas muestran el tratamiento realizado a todos los demás eventos.

Page 63: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

63

Aplicación scada

Page 64: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

64

Aplicación cliente lectura

EVENTO

OnConnectWinsock1()

Flag PASS y Remote activadosAviso por pantalla

de introducir contraseña Anula

temporizador.Flag Remote desactivado

Si mensaje es “aceptado”:

Flag Remote activado, flag

PASS desactivado y

reinicio socket 1

Cierra socket si se destruye la

ventana y envia una petición de borrado de la conexión del

cliente

Inicia parámetros y variables del

sistema

OnTimer(UINT nIDEvent)

OnDataArrivalWinsock1(long bytesTotal)

OnDestroy()

OnInitDialog()

CLIENTE LECTURA ON

Envío mensaje “obtener” al

Servidor.Flag Remote

activado

OnConnectWinsock2()

Muestra consigna recibida del Servidor por

pantalla.Flag obtener desactivado

OnDataArrivalWinsock2(long bytesTotal)

Remote?

Indica error en el sistema.

Flag obtener desactivado

SI NO

Page 65: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

65

Aplicación cliente escritura

EVENTO

PASS?

OnConectar()

Retorno al menú principal

Conectado con servidor?

Conecta con el servidor y

activa flag PASS

"El sistema ya esta conectado"

NOP

NO SIConectado con

servidor?

OnActualizar()

OnActualizar()

Informa de que el sistema ya esta

conectadoNOP

NO SI

NOPSe envía

contraseña al servidor

NO SI

OnConfirmarPassword() Volver

CLIENTE ESCRITURA ON

Si el sistema esta conectado con el

servidor se solicita la información, en caso contrario se

informa por pantalla de que el sistema no esta

conectado

OnObtener()

Si el sistema esta conectado con el servidor se envía

la consigna

OnEnviar()

EVENTOOnConnectWinsock1()

Pide la petición de contraseña por

parte del Servidor

Si Flag PASS esta desactivado, actualiza el estado de

conexión con el servidor por

pantalla

Cierra socket si se destruye la

ventana

Inicia parámetros y variables del

sistema

OnTimer(UINT nIDEvent)

OnDataArrivalWinsock1(long bytesTotal)

OnDestroy() OnInitDialog()

CLIENTE ESCRITURA ON

Valida la consigna si esta dentro del rango establecido

OnChangeConsigna()

Dato recibido

Se informa por pantalla que el

scada esta desconectado.

Se desconecta del servidor.

Se reinicia socket

Se informa por pantalla la petición de

introducción de contraseña.Flag PASS

activado

Se informa por pantalla que el sistema esta

conectado con el servidor.

Flag PASS desactivado

Se actualiza por pantalla la

temperatura actual del sistema

SCADA OFF

PASSConectado

Consigna

Page 66: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

66

Aplicación servidor

Page 67: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

67

Page 68: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

68

Conclusiones

Page 69: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

69

Conclusiones

La aplicación desarrollada en el proyecto es capaz de realizar el control y monitorización remota de un proceso industrial a través de cualquier tipo de red Ethernet basada en el protocolo TCP/IP.

Dado el espectro disponible de opciones de este tipo de red en el mercado y su gran estandarización, la aplicación nos ofrece una gran variedad de combinaciones posibles. Estas combinaciones se pueden crear en base de las necesidades cambiantes de los usuarios.

Por ejemplo no todos los usuarios dispondrán de una conexión de red local en planta y necesitaran estaciones independientes conectadas a internet que puedan interconectarse de forma segura con el proceso. También se ha desarrollado una opción para poder trabajar sin una estación de servidor con dirección IP estática, en el proyecto se ha expuesto una solución a este problema pero existen varias soluciones eficaces y eficientes.

También pueden surgir otras problemáticas de falta de recursos o de cambios en la estructura de la red, que en el proyecto se han resuelto satisfactoriamente, creando una aplicación donde el usuario puede ir variando los parámetros de conexión. Esta versatilidad combinada con la facilidad de manejo de la aplicación, por parte del usuario, se convierte en uno de los puntos fuertes del sistema desarrollado.

Se ha conseguido integrar las diferentes aplicaciones cliente en una sola aplicación donde se podrá escoger, según el grado de privilegio del usuario y las necesidades de este, la aplicación más idónea. Todas las aplicaciones cliente mantienen un formato similar para conseguir la adaptación rápida del usuario en la aplicación.

Se ha intentado exponer, de forma funcional, en este proyecto los fundamentos básicos que conforman el eje del sistema. Estos conceptos como la funcionalidad de los sockets y de transmisión de datos, son clave para poder entender el procedimiento del sistema.

Teniendo en cuenta la motivación pedagógica de este proyecto, se podría realizar algunas posibles líneas de continuación como crear la interface necesaria para comunicar el proceso industrial con la aplicación scada, crear una base de datos externa de todos los usuarios y un historial de conexiones, ampliar la consigna del proceso a más de una pudiendo simular el control total de un proceso industrial, posibilidad de encriptar la información transmitida en red, realizar la transcripción del código a otros lenguajes como java para crear una interface basada en http (páginas web)…

Este proyecto también puede ser utilizado como base para realizar cualquier tipo de implementación de un sistema múltiple cliente servidor.

Al ir avanzando en la programación de la aplicación se han corregido bastantes errores producidos en gran mayoría por problemas de comunicación entre los sockets, se han ejecutado tests de pruebas, de forma satisfactoria, para comprobar la estabilidad del sistema y de las conexiones realizadas eventualmente entre aplicaciones.

Page 70: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

70

Gran parte del éxito de este proyecto radica en el estudio anterior sobre programación en c, aportado en asignaturas realizadas en el transcurso de la carrera y de la información obtenida en la bibliografía documentada en el apartado referencias de este documento.

También ha sido de gran utilidad la información obtenida vía internet de los diferentes aspectos de comunicación entre sockets que han ayudado a corregir algunos errores aparecidos en el transcurso de la elaboración de este proyecto.

En el anexo añadimos el código de todos los archivos que se incluyen en el proyecto de Microsoft Visual C++.

Page 71: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

71

Referencias

Page 72: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

72

[1] Kris Jamsa y Ken Cope, Programación en internet, McGraw-Hill, 1997.

[2] W. Richard Stevens 1990. “UNIX Network Programming”, Prentice-Hall.

[3] Pagina Web http://www.microsoft.com

[4] B.W. Kernighan y R. Pike 1987, “El entorno de programación UNIX”, Prentice-Hall.

[5] C++ Cómo programar Cuarta edición por Deitel y Deitel, 2003.

[6] David Kruglinski, George Shepherd, Scot Wingo. PROGRAMACIÓN AVANZADA CON MICROSOFT VISUAL C++ 6.0, McGraw-Hill, 2003.

[7] Kate Gregory. EDICIÓN ESPECIAL VISUAL C++ 6, Prentice-Hall, 1999.

[8] Microsoft Developer Network, http://msdn.microsoft.com

Page 73: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

73

APLICACIÓN SCADA BASADA EN

COMUNICACIÓN TCP/IP

MANUAL USUARIO

Page 74: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

74

INDICE

Configuración del hardware___________________________________71

Aplicación servidor________________________71

Aplicación cliente_________________________78

Instalación________________________________________________ 79

Servidor 79

Cliente 80

Funcionamiento de la aplicación______________________________ 81

Servidor 82

Cliente 82

Page 75: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

75

Page 76: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

76

Configuración del hardware

Aplicación servidor

Para poder utilizar correctamente la aplicación servidor se deberán tener en cuenta los siguientes factores:

¿Disponemos de una Intranet?

¿Qué servicio de acceso a internet tiene la estación donde reside la aplicación?

¿Con qué tipo de dispositivo realizamos la conexión a Internet?

¿IP de la estación dinámica o estática?

¿Sistema operativo de la estación?

Después de realizar estas preguntas se puede observar que la configuración del sistema puede ser variable y que cada configuración tendrá sus diferentes pasos a seguir.

Algunas configuraciónes nos permitirán trabajar con un sistema más estable, evitando perdidas de conexión por parte del servidor e evitar errores con los datos del proceso.

La configuración más adecuada para el correcto funcionamiento del servidor será la siguiente:

S.O. Windows Server 2003

Red local instalada en la planta donde reside el proceso y el servidor

Servidor con dirección IP estática

Dispositivos de conexión a la red con alimentación ininterrumpida (SAI)

Acceso a internet por medio de Proxy3

Con esta configuración la aplicación podrá funcionar perfectamente sin ningún tipo de configuración adicional, simplemente se deberá tener en cuenta que los cortafuegos y antivirus del sistema operativo instalado nos permitan el acceso a las aplicaciones.

Si no disponemos de tal configuración también se puede ejecutar la aplicación con cualquier sistema operativo Windows conectado a una red local o a Internet. El gran inconveniente de no disponer una dirección IP estática es que con la IP dinámica la 3 Proxy hace referencia a un programa o dispositivo que realiza una acción en representación de otro. Su finalidad más habitual es la de servidor proxy, que sirve para permitir el acceso a Internet a todos los equipos de una organización cuando sólo se puede disponer de un único equipo conectado, esto es, una única dirección IP.

Page 77: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

77

dirección cambia a voluntad del proveedor, normalmente cuando reseteamos nuestro router/modem.

Configuración para trabajar con IP dinámica

La solución planteada aquí es usar un servicio de nombrado dinámico, es decir que sea capaz de trabajar con una IP dinámica. Para que esto funcione, necesitamos que nuestro servidor informe al servicio de nombrado cada vez que nuestro ISP nos cambie la IP, de este modo el servicio de nombres estará actualizado.

Hay varios proveedores de servicios de nombrado dinámico (estos son sólo algunos de ellos):

• No-IP

• ZoneEdit

• DynDNS

Además se necesita un software en el sistema operativo que se comunique con el servicio de nombrado dinámico.

A continuación se describe, a modo de ejemplo, una configuración del servidor:

Page 78: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

78

El servidor estará normalmente en una red local, conectado a Internet mediante un Router, se tendra que configurar la red local y el router.

Ahora tendremos que darnos de alta en No-IP, y crear una cuenta gratuita, una vez hecho esto, tendremos que dar de alta el (o los) nombre de dominio que queremos, en el caso de No-IP nos dan a elegir entre subdominios. Una vez iniciada sesión en la cuenta de No-IP, se introducen los valores de YOUR NO-IP, Hosts/Redirects, Add .

Para averiguar la IP actual del Servidor se puede ejecutar directamente la aplicación y observar la dirección que aparece en pantalla o ir a la aplicación Ms-Dos de Windows (Inicio-Todos los programas-Accesorios-Simbolo del sistema). Dentro de la aplicación ejecutar “ipconfig” y aparecerá una ventana como esta:

La dirección actual del sistema de este caso sería 192.168.1.2

Configuración del Router

Ejemplo mostrado para el modelo de router Zyxel Prestige 660R-61C, para otro modelo de router mirar el manual del fabricante.

1) Abrimos una nueva ventana del explorador y escribimos 192.168.1.1 (por defecto).

2) Aparecerá una ventana pidiendo usuario y contraseña. Por defecto es 1234 en ambas casillas, si no pueden ingresar con estos datos, van a tener que conseguirlos ya que no

Page 79: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

79

van a poder continuar.

Una vez ingresados los datos, clickeamos en Aceptar

3) Aparecerá el menú principal del router, llamado Site Map. Lo que nos interesa se encuentra en la opción NAT de la columna Advanced Setup. Clickeamos ahí.

4) Nos aparecerá la pantalla NAT - Mode.

Page 80: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

80

Seleccionamos la opción SUA Only y clickeamos en Edit Details de esa misma opción. 5) Aparece la pantalla con los re direccionamientos. Hay 12 casillas.

Page 81: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

81

Ahora viene la parte más sencilla. En la columna Start Port No. vamos a escribir el número del puerto en donde se comenzará a abrir. En la columna End Port No. escribiremos el número del puerto en donde se terminará de abrir. Por ejemplo, si quiero abrir todos los puertos desde el 70 al 80, escribo 70 en Start Port No. y 80 en End Port No.. Si quiero abrir un sólo puerto, escribo el mismo número en ambas casillas. En la columna IP Adress debemos escribir la dirección IP interna de nuestra PC, es decir, la dirección IP de nuestra PC en la red (no es la IP pública). Para descubrir la IP actual de nuestro sistema seguir los pasos detallados en la configuración anterior.

Ésa es la dirección IP que debemos ingresar en la tercer columna, tal como aparece en la consola de MS-DOS. Por ejemplo, si nuestra aplicación utiliza los puertos 4662 y 4672, y nuestra dirección IP interna es 192.168.1.2, quedaría de la siguiente manera:

6) Para terminar realizamos un clic en el botón Save y listo, las conexiones que entren, en este caso, por los puertos 4662 y 4672 se re direccionarán a nuestro sistema y podremos recibir las notificaciones sin problemas.

Page 82: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

82

Aplicación Cliente

La configuración del sistema para el correcto funcionamiento de la aplicación cliente es cualquiera que posea una conexión a internet y un sistema operativo Windows. Tener en cuenta también que las aplicaciones de antivirus y cortafuegos nos permitan el acceso al exterior de la aplicación.

Page 83: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

83

Instalación

Servidor

Para instalar la aplicación Servidor bastara con ejecutar la aplicación

“PFC-EGP-Servidor.exe”

Y seguir las instrucciones que nos aparecerán en pantalla

Finalmente en la pantalla que nos aparecerá, registrar archivo “MSWINSCK.OCX”

Cliente

Para la instalación de la aplicación cliente se realizarán los mismos pasos que en la instalación de la aplicación servidor.

Page 84: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

84

Funcionamiento de la aplicación El software realizado (Cliente.exe, Servidor.Exe) se debe instalar en un ordenador PC compatible con el sistema operativo Windows.

Dependiendo de cuál sea la ubicación se instalara una aplicación o otra:

En el ordenador donde está conectado el proceso industrial instalaremos la aplicación Cliente (Scada), esta aplicación se encargara de captar los datos del sensor y enviar la consigna deseada.

En el ordenador donde reside el ordenador Servidor con conexión al exterior instalaremos la aplicación Servidor.exe, esta aplicación se encargara de guardar los datos del proceso y enviarlos debidamente a los destinatarios, también enviara la consigna deseada al ordenador del proceso cuando tenga activada esta opción.

En todos los demás ordenadores pertenecientes a la red LAN o WAN se podrá instalar la aplicación cliente y trabajar como lectura o escritura, la diferencia entre estas dos aplicaciones reside en el hecho de que lectura sólo puede leer los datos del sensor mientras que escritura puede leer y enviar la consigna deseada cuando el ordenador del proceso tenga activada esta opción.

La aplicación escritura sólo funcionará desde una única ubicación, aunque esta se puede variar dependiendo de las necesidades de la planta, el motivo de esta configuración es la de evitar posibles datos erróneos en la consigna del proceso.

A continuación se mostraran todas la pantallas detalladas de los menús pertenecientes a cada aplicación.

Page 85: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

85

Servidor

Cliente

Page 86: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

86

Aplicación Scada:

Cliente lectura:

Page 87: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

87

Cliente escritura:

Page 88: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

88

ANEXOS

Page 89: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

89

MSWinsockControl.cpp

// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++ // NOTE: Do not modify the contents of this file. If this class is regenerated by // Microsoft Visual C++, your modifications will be overwritten. #include "stdafx.h" #include "mswinsockcontrol.h" ///////////////////////////////////////////////////////////////////////////// // CMSWinsockControl IMPLEMENT_DYNCREATE(CMSWinsockControl, CWnd) ///////////////////////////////////////////////////////////////////////////// // CMSWinsockControl properties ///////////////////////////////////////////////////////////////////////////// // CMSWinsockControl operations long CMSWinsockControl::GetProtocol() { long result; InvokeHelper(0x3, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL); return result; } void CMSWinsockControl::SetProtocol(long nNewValue) { static BYTE parms[] = VTS_I4; InvokeHelper(0x3, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, nNewValue); } CString CMSWinsockControl::GetRemoteHostIP() { CString result; InvokeHelper(0x4, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL); return result; } CString CMSWinsockControl::GetLocalHostName() { CString result; InvokeHelper(0x5, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL); return result; } CString CMSWinsockControl::GetLocalIP() { CString result; InvokeHelper(0x6, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL); return result; } long CMSWinsockControl::GetSocketHandle() { long result; InvokeHelper(0x7, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL); return result; } long CMSWinsockControl::GetRemotePort() { long result; InvokeHelper(0x1, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL); return result; } void CMSWinsockControl::SetRemotePort(long nNewValue) {

Page 90: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

90

static BYTE parms[] = VTS_I4; InvokeHelper(0x1, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, nNewValue); } long CMSWinsockControl::GetLocalPort() { long result; InvokeHelper(0x2, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL); return result; } void CMSWinsockControl::SetLocalPort(long nNewValue) { static BYTE parms[] = VTS_I4; InvokeHelper(0x2, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, nNewValue); } short CMSWinsockControl::GetState() { short result; InvokeHelper(0x8, DISPATCH_PROPERTYGET, VT_I2, (void*)&result, NULL); return result; } long CMSWinsockControl::GetBytesReceived() { long result; InvokeHelper(0x9, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL); return result; } void CMSWinsockControl::Connect(const VARIANT& RemoteHost, const VARIANT& RemotePort) { static BYTE parms[] = VTS_VARIANT VTS_VARIANT; InvokeHelper(0x40, DISPATCH_METHOD, VT_EMPTY, NULL, parms, &RemoteHost, &RemotePort); } void CMSWinsockControl::Listen() { InvokeHelper(0x41, DISPATCH_METHOD, VT_EMPTY, NULL, NULL); } void CMSWinsockControl::Accept(long requestID) { static BYTE parms[] = VTS_I4; InvokeHelper(0x42, DISPATCH_METHOD, VT_EMPTY, NULL, parms, requestID); } void CMSWinsockControl::SendData(const VARIANT& data) { static BYTE parms[] = VTS_VARIANT; InvokeHelper(0x43, DISPATCH_METHOD, VT_EMPTY, NULL, parms, &data); } void CMSWinsockControl::GetData(VARIANT* data, const VARIANT& type, const VARIANT& maxLen) { static BYTE parms[] = VTS_PVARIANT VTS_VARIANT VTS_VARIANT; InvokeHelper(0x44, DISPATCH_METHOD, VT_EMPTY, NULL, parms, data, &type, &maxLen); } void CMSWinsockControl::PeekData(VARIANT* data, const VARIANT& type, const VARIANT& maxLen) { static BYTE parms[] =

Page 91: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

91

VTS_PVARIANT VTS_VARIANT VTS_VARIANT; InvokeHelper(0x45, DISPATCH_METHOD, VT_EMPTY, NULL, parms, data, &type, &maxLen); } void CMSWinsockControl::Close() { InvokeHelper(0x46, DISPATCH_METHOD, VT_EMPTY, NULL, NULL); } void CMSWinsockControl::Bind(const VARIANT& LocalPort, const VARIANT& LocalIP) { static BYTE parms[] = VTS_VARIANT VTS_VARIANT; InvokeHelper(0x47, DISPATCH_METHOD, VT_EMPTY, NULL, parms, &LocalPort, &LocalIP); } CString CMSWinsockControl::GetRemoteHost() { CString result; InvokeHelper(0xa, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL); return result; } void CMSWinsockControl::SetRemoteHost(LPCTSTR lpszNewValue) { static BYTE parms[] = VTS_BSTR; InvokeHelper(0xa, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, lpszNewValue); }

Page 92: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

92

MSWinsockControl.h

#if !defined(AFX_MSWINSOCKCONTROL_H__5F5F6292_64DE_48DD_A382_A558E468340A__INCLUDED_) #define AFX_MSWINSOCKCONTROL_H__5F5F6292_64DE_48DD_A382_A558E468340A__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 // Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++ // NOTE: Do not modify the contents of this file. If this class is regenerated by // Microsoft Visual C++, your modifications will be overwritten. ///////////////////////////////////////////////////////////////////////////// // CMSWinsockControl wrapper class class CMSWinsockControl : public CWnd { protected: DECLARE_DYNCREATE(CMSWinsockControl) public: CLSID const& GetClsid() { static CLSID const clsid = { 0x248dd896, 0xbb45, 0x11cf, { 0x9a, 0xbc, 0x0, 0x80, 0xc7, 0xe7, 0xb7, 0x8d } }; return clsid; } virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL) { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID); } BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CFile* pPersist = NULL, BOOL bStorage = FALSE, BSTR bstrLicKey = NULL) { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID, pPersist, bStorage, bstrLicKey); } // Attributes public: // Operations public: long GetProtocol(); void SetProtocol(long nNewValue); CString GetRemoteHostIP(); CString GetLocalHostName(); CString GetLocalIP(); long GetSocketHandle(); long GetRemotePort(); void SetRemotePort(long nNewValue); long GetLocalPort(); void SetLocalPort(long nNewValue); short GetState(); long GetBytesReceived(); void Connect(const VARIANT& RemoteHost, const VARIANT& RemotePort); void Listen(); void Accept(long requestID); void SendData(const VARIANT& data); void GetData(VARIANT* data, const VARIANT& type, const VARIANT& maxLen); void PeekData(VARIANT* data, const VARIANT& type, const VARIANT& maxLen); void Close(); void Bind(const VARIANT& LocalPort, const VARIANT& LocalIP); CString GetRemoteHost(); void SetRemoteHost(LPCTSTR lpszNewValue); }; //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line.

Page 93: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

93

#endif // !defined(AFX_MSWINSOCKCONTROL_H__5F5F6292_64DE_48DD_A382_A558E468340A__INCLUDED_)

Page 94: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

94

server.rc

//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by server.rc // #define IDOK2 2 #define IDOK3 3 #define IDOK4 4 #define IDOK5 5 #define IDOK6 6 #define IDOK7 7 #define IDM_ABOUTBOX 0x0010 #define IDD_ABOUTBOX 100 #define IDS_ABOUTBOX 101 #define IDD_SERVER_DIALOG 102 #define IDP_SOCKETS_INIT_FAILED 103 #define IDR_MAINFRAME 128 #define IDC_EDIT1 1001 #define IDC_EDIT2 1002 #define IDC_WINSOCK1 1003 #define IDC_EDIT3 1005 #define IDC_EDIT4 1006 #define IDC_ANIMATE1 1007 #define IDC_EDIT5 1007 #define IDC_WINSOCK2 1008 #define IDC_EDIT6 1009 #define IDC_EDIT7 1010 #define IDC_WINSOCK3 1011 #define IDC_WINSOCK4 1012 #define IDC_EDIT8 1013 #define IDC_EDIT9 1014 #define IDC_EDIT10 1015 #define IDC_BUTTON2 1016 #define IDC_EDIT11 1017 #define IDC_EDIT12 1018 #define IDC_EDIT16 1019 #define IDC_EDIT17 1020 #define IDC_EDIT18 1021 #define IDC_EDIT13 1022 #define IDC_EDIT14 1023 #define IDC_EDIT15 1024 #define IDC_EDIT19 1025 #define IDC_EDIT20 1026 #define IDC_EDIT21 1027 #define IDC_EDIT22 1028 #define IDC_EDIT23 1029 #define IDC_EDIT24 1030 #define IDC_BUTTON1 1031 #define IDC_WINSOCK5 1032 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 132 #define _APS_NEXT_COMMAND_VALUE 32771 #define _APS_NEXT_CONTROL_VALUE 1033 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif

Page 95: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

95

Server.cpp

// server.cpp : Defines the class behaviors for the application. // #include "stdafx.h" #include "server.h" #include "serverDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CServerApp BEGIN_MESSAGE_MAP(CServerApp, CWinApp) //{{AFX_MSG_MAP(CServerApp) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG ON_COMMAND(ID_HELP, CWinApp::OnHelp) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CServerApp construction CServerApp::CServerApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance } ///////////////////////////////////////////////////////////////////////////// // The one and only CServerApp object CServerApp theApp; ///////////////////////////////////////////////////////////////////////////// // CServerApp initialization BOOL CServerApp::InitInstance() { if (!AfxSocketInit()) { AfxMessageBox(IDP_SOCKETS_INIT_FAILED); return FALSE; } AfxEnableControlContainer(); // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need. #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif CServerDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { }

Page 96: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

96

// Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; }

Page 97: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

97

Server.h

// server.h : main header file for the SERVER application // #if !defined(AFX_SERVER_H__ABA7404C_5318_41FF_A149_C9085DF1C3AB__INCLUDED_) #define AFX_SERVER_H__ABA7404C_5318_41FF_A149_C9085DF1C3AB__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #ifndef __AFXWIN_H__ #error include 'stdafx.h' before including this file for PCH #endif #include "resource.h" // main symbols #include <io.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> ///////////////////////////////////////////////////////////////////////////// // CServerApp: // See server.cpp for the implementation of this class // class CServerApp : public CWinApp { public: CServerApp(); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CServerApp) public: virtual BOOL InitInstance(); //}}AFX_VIRTUAL // Implementation //{{AFX_MSG(CServerApp) // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_SERVER_H__ABA7404C_5318_41FF_A149_C9085DF1C3AB__INCLUDED_)

Page 98: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

98

ServerDlg.cpp

// serverDlg.cpp : implementation file // #include "stdafx.h" #include "server.h" #include "serverDlg.h" #include "usuarios.h" #include <io.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About CMSWinsockControl proba; class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CServerDlg dialog CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/) : CDialog(CServerDlg::IDD, pParent) {

Page 99: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

99

//{{AFX_DATA_INIT(CServerDlg) m_edit1 = _T(""); m_edit2 = _T("OFF"); //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); //proba.SetRemoteHost(m_host); //proba.SetRemotePort(atoi(m_port)); } void CServerDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CServerDlg) DDX_Control(pDX, IDOK, m_ok); DDX_Text(pDX, IDC_EDIT1, m_edit1); DDX_Text(pDX, IDC_EDIT2, m_edit2); DDX_Control(pDX, IDC_WINSOCK2, m_socket2); DDX_Control(pDX, IDC_WINSOCK1, m_socket1); DDX_Control(pDX, IDC_WINSOCK3, m_socket3); DDX_Control(pDX, IDC_WINSOCK4, m_socket4); DDX_Control(pDX, IDC_WINSOCK5, m_socket5); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CServerDlg, CDialog) //{{AFX_MSG_MAP(CServerDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_TIMER() ON_EN_CHANGE(IDC_EDIT1, OnTactual) ON_BN_CLICKED(IDOK, OnEnviarres) ON_EN_CHANGE(IDC_EDIT2, OnChangeConsigna) ON_BN_CLICKED(IDC_BUTTON2, OnValidarPSWRW) ON_WM_DESTROY() ON_BN_CLICKED(IDC_BUTTON1, OnCambiarPSW) ON_BN_CLICKED(IDOK7, OnEnableClient0) ON_BN_CLICKED(IDOK3, OnEnableClient1) ON_BN_CLICKED(IDOK4, OnEnableClient2) ON_BN_CLICKED(IDOK6, OnEnableClient4) ON_BN_CLICKED(IDOK5, OnEnableClient3) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CServerDlg message handlers BOOL CServerDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon

Page 100: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

100

SetIcon(m_hIcon, FALSE); // Set small icon // Inicializamos las variables del sistema y la información de pantalla CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT5); //captamos contenido edit pEdit->SetWindowText("Desconectado"); CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT1); //captamos contenido edit pEdit1->SetWindowText("OFF"); PasswordRW="master"; CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT3); //captamos contenido edit pEdit2->SetWindowText(PasswordRW); ServerOK=TRUE; LocalIP = m_socket1.GetLocalIP(); CEdit* pEdit3 = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit3->SetWindowText(LocalIP); //Captamos la dirección actual del servidor EnableClient0=TRUE; EnableClient1=TRUE; EnableClient2=TRUE; EnableClient3=TRUE; EnableClient4=TRUE; EnableALL=TRUE; //Habilitamos Todos los clientes InitSocket(); //Inicializamos los sockets return TRUE; // return TRUE unless you set the focus to a control } void CServerDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CServerDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } }

Page 101: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

101

// The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CServerDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } BEGIN_EVENTSINK_MAP(CServerDlg, CDialog) //{{AFX_EVENTSINK_MAP(CServerDlg) ON_EVENT(CServerDlg, IDC_WINSOCK1, 1 /* Connect */, OnConnectWinsock1, VTS_NONE) ON_EVENT(CServerDlg, IDC_WINSOCK1, 2 /* ConnectionRequest */, OnConnectionRequestWinsock1, VTS_I4) ON_EVENT(CServerDlg, IDC_WINSOCK1, 0 /* DataArrival */, OnDataArrivalWinsock1, VTS_I4) ON_EVENT(CServerDlg, IDC_WINSOCK1, 5 /* Close */, OnCloseWinsock1, VTS_NONE) ON_EVENT(CServerDlg, IDC_WINSOCK2, 2 /* ConnectionRequest */, OnConnectionRequestWinsock2, VTS_I4) ON_EVENT(CServerDlg, IDC_WINSOCK2, 0 /* DataArrival */, OnDataArrivalWinsock2, VTS_I4) ON_EVENT(CServerDlg, IDC_WINSOCK2, 5 /* Close */, OnCloseWinsock2, VTS_NONE) ON_EVENT(CServerDlg, IDC_WINSOCK4, 2 /* ConnectionRequest */, OnConnectionRequestWinsockClienteR, VTS_I4) ON_EVENT(CServerDlg, IDC_WINSOCK4, 0 /* DataArrival */, OnDataArrivalWinsockClienteR, VTS_I4) ON_EVENT(CServerDlg, IDC_WINSOCK4, 5 /* Close */, OnCloseWinsockClienteR, VTS_NONE) ON_EVENT(CServerDlg, IDC_WINSOCK3, 5 /* Close */, OnCloseWinsock3, VTS_NONE) ON_EVENT(CServerDlg, IDC_WINSOCK3, 2 /* ConnectionRequest */, OnConnectionRequestWinsockClienteRDatos, VTS_I4) ON_EVENT(CServerDlg, IDC_WINSOCK3, 0 /* DataArrival */, OnDataArrivalWinsockClienteRDatos, VTS_I4) ON_EVENT(CServerDlg, IDC_WINSOCK3, 4 /* SendComplete */, OnSendCompleteWinsockClienteRDatos, VTS_NONE) ON_EVENT(CServerDlg, IDC_WINSOCK5, 2 /* ConnectionRequest */, OnConnectionRequestWinsockClienteRExit, VTS_I4) ON_EVENT(CServerDlg, IDC_WINSOCK2, 4 /* SendComplete */, OnSendCompleteWinsock2, VTS_NONE) ON_EVENT(CServerDlg, IDC_WINSOCK5, 5 /* Close */, OnCloseWinsock5, VTS_NONE) //}}AFX_EVENTSINK_MAP END_EVENTSINK_MAP() void CServerDlg::OnConnectWinsock1() { // TODO: Add your control notification handler code here } //Evento pertenceciente al botón habilitar o deshabilitar a todos los clientes void CServerDlg::OnEnviarres() { if(EnableALL) { EnableClient0=FALSE; EnableClient1=FALSE; EnableClient2=FALSE; EnableClient3=FALSE; EnableClient4=FALSE; EnableALL=FALSE; AfxMessageBox ("Clientes deshabilitados"); } else { EnableClient0=TRUE; EnableClient1=TRUE; EnableClient2=TRUE; EnableClient3=TRUE; EnableClient4=TRUE; EnableALL=TRUE; AfxMessageBox ("Clientes habilitados"); } } //Evento perteneciente a la petición de conexión del socket 1

Page 102: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

102

void CServerDlg::OnConnectionRequestWinsock1(long requestID) { CString IP; m_socket1.Close(); vtHost.vt=VT_BSTR; vtHost.bstrVal=IP.AllocSysString(); m_socket1.Accept(requestID); //Aceptamos conexión Socket1=TRUE; //Activamos flag de conexión con scada CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT5); //captamos contenido edit pEdit->SetWindowText("Conectado"); } //Evento perteneciente a la recepción de datos del socket 1 void CServerDlg::OnDataArrivalWinsock1(long bytesTotal) { CString strport; VARIANT vtData; VARIANT vtType; VARIANT vtMaxlen; strport="4000"; vtData.vt=VT_BSTR; vtType.vt=VT_ERROR; vtMaxlen.vt=VT_I2; vtMaxlen.iVal=(short)bytesTotal; CString mensaje; vtData.bstrVal=strport.AllocSysString(); vtType.bstrVal=strport.AllocSysString(); m_socket1.GetData(&vtData,vtType,vtMaxlen); mensaje=vtData.bstrVal; //Recogemos el mensaje if(mensaje=="Desconectar") { m_socket1.Close(); m_socket1.Listen(); m_socket2.Close(); m_socket2.Listen(); Socket1=FALSE; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT5); //captamos contenido edit pEdit->SetWindowText("Desconectado"); CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT1); pEdit1->SetWindowText("OFF"); CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT2); pEdit2->SetWindowText("OFF"); //Si el mensaje es desonectar cerramos la conexión con scada y cliente escritura } else { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT1); pEdit->SetWindowText(mensaje); //Actualizamos temperatura actual } } //Evento perteneciente al cierre del socket 1 void CServerDlg::OnCloseWinsock1() { OnCloseWinsock2(); Socket1=FALSE; //Desactivamos el flag de conexión con scada m_socket1.Close(); m_socket1.Listen(); //Reiniciamos socket 1 CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT5); pEdit->SetWindowText("Desconectado"); CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT1); pEdit1->SetWindowText("OFF"); CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT2); pEdit2->SetWindowText("OFF"); //Informamos por pantalla

Page 103: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

103

} //Inicialización de los sockets void CServerDlg::InitSocket() { //////CONFIGURACIÓN PUERTOS///////////////////// m_host = LocalIP; m_port = "888"; m_port2 = "889"; m_port3 = "891"; m_port4 = "890"; m_port5 = "892"; //////////////////////////////////////////////// Socket1=FALSE; //Flag socket1 desactivado Password=FALSE; //Flag Password descativado vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); m_socket1.SetLocalPort(atoi(m_port)); //El proceso servidor crea ("abre") el socket servidor(socket) //m_socket1.Bind(vtPort,vtHost); //le asigna un puerto (bind) en la máquina servidora m_socket1.Listen(); //prepara para la escucha CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT10); pEdit1->SetWindowText(m_port); vtPort.bstrVal=m_port2.AllocSysString(); m_socket2.SetLocalPort(atoi(m_port2)); //m_socket2.Bind(vtPort,vtHost); m_socket2.Listen(); CEdit* pEdit13 = (CEdit*) GetDlgItem(IDC_EDIT8); pEdit13->SetWindowText(m_port2); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port4.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT9); pEdit2->SetWindowText(m_port4); vtPort.bstrVal=m_port4.AllocSysString(); m_socket4.SetLocalPort(atoi(m_port4)); //m_socket4.Bind(vtPort,vtHost); m_socket4.Listen(); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port3.AllocSysString(); m_socket3.SetLocalPort(atoi(m_port3)); //m_socket3.Bind(vtPort,vtHost); m_socket3.Listen(); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port5.AllocSysString(); m_socket5.SetLocalPort(atoi(m_port5)); //m_socket5.Bind(vtPort,vtHost); m_socket5.Listen();

Page 104: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

104

/////////Creación de la base de datos de los clientes////////// m_ListaUsuarios[0] = new CUsuarios; strcpy(m_ListaUsuarios[0]->m_strPass , "juan123"); strcpy(m_ListaUsuarios[0]->m_strIP , "0"); CEdit* pEdit3 = (CEdit*) GetDlgItem(IDC_EDIT7); pEdit3->SetWindowText("juan"); CEdit* pEdit4 = (CEdit*) GetDlgItem(IDC_EDIT12); pEdit4->SetWindowText("juan123"); m_ListaUsuarios[1] = new CUsuarios; strcpy(m_ListaUsuarios[1]->m_strPass , "pedro123"); strcpy(m_ListaUsuarios[1]->m_strIP , "0"); CEdit* pEdit5 = (CEdit*) GetDlgItem(IDC_EDIT13); pEdit5->SetWindowText("pedro"); CEdit* pEdit6 = (CEdit*) GetDlgItem(IDC_EDIT15); pEdit6->SetWindowText("pedro123"); m_ListaUsuarios[2] = new CUsuarios; strcpy(m_ListaUsuarios[2]->m_strPass , "maria123"); strcpy(m_ListaUsuarios[2]->m_strIP , "0"); CEdit* pEdit7 = (CEdit*) GetDlgItem(IDC_EDIT16); pEdit7->SetWindowText("maria"); CEdit* pEdit8 = (CEdit*) GetDlgItem(IDC_EDIT18); pEdit8->SetWindowText("maria123"); m_ListaUsuarios[3] = new CUsuarios; strcpy(m_ListaUsuarios[3]->m_strPass , "demian123"); strcpy(m_ListaUsuarios[3]->m_strIP , "0"); CEdit* pEdit9 = (CEdit*) GetDlgItem(IDC_EDIT19); pEdit9->SetWindowText("demian"); CEdit* pEdit10 = (CEdit*) GetDlgItem(IDC_EDIT21); pEdit10->SetWindowText("demian123"); m_ListaUsuarios[4] = new CUsuarios; strcpy(m_ListaUsuarios[4]->m_strPass , "pepe123"); strcpy(m_ListaUsuarios[4]->m_strIP , "0"); CEdit* pEdit11 = (CEdit*) GetDlgItem(IDC_EDIT22); pEdit11->SetWindowText("pepe"); CEdit* pEdit12 = (CEdit*) GetDlgItem(IDC_EDIT24); pEdit12->SetWindowText("pepe123"); ////////////////////////////////////////////////////////////// } //Evento temporizador void CServerDlg::OnTimer(UINT nIDEvent) { CString mensaje; CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT1); //captamos contenido edit pEdit1->GetWindowText(mensaje); if(mensaje!="OFF") { //OnEnviarres(); } } //Actualización temperatura actual void CServerDlg::OnTactual() { CString Data; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT1); //captamos contenido edit pEdit->GetWindowText(Data); } //Evento perteneciente a la petición de conexión del socket 2 void CServerDlg::OnConnectionRequestWinsock2(long requestID) {

Page 105: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

105

long Port; CString IP; BOOL encontrado=FALSE; //Si hay conexión con Scada conectamos con cliente escritura if(Socket1==TRUE) { m_socket2.Close(); IP = m_socket2.GetRemoteHostIP(); Port = m_socket2.GetRemotePort(); vtHost.vt=VT_BSTR; vtHost.bstrVal=IP.AllocSysString(); m_socket2.Accept(requestID); } //Si no hay conexión con Scada avisamos al cliente else { m_socket2.Close(); IP = m_socket2.GetRemoteHostIP(); Port = m_socket2.GetRemotePort(); vtHost.vt=VT_BSTR; vtHost.bstrVal=IP.AllocSysString(); m_socket2.Accept(requestID); VARIANT vtDato; CString Dato; Dato = "SCADA OFF"; vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket2.SendData(vtDato); } } //Evento perteneciente a la recepción de datos del socket 2 void CServerDlg::OnDataArrivalWinsock2(long bytesTotal) { CString strport; VARIANT vtData; VARIANT vtType; VARIANT vtMaxlen; strport="4000"; vtData.vt=VT_BSTR; vtType.vt=VT_ERROR; vtMaxlen.vt=VT_I2; vtMaxlen.iVal=(short)bytesTotal; CString mensaje; vtData.bstrVal=strport.AllocSysString(); vtType.bstrVal=strport.AllocSysString(); m_socket2.GetData(&vtData,vtType,vtMaxlen); mensaje=vtData.bstrVal; //Introducimos consigna al sistema if(mensaje!="Obtener"&&mensaje!="PASS"&&mensaje!="master"&&Socket1==TRUE&&Password==TRUE) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT2); pEdit->SetWindowText(mensaje); } //Realizamos petición de password al cliente if(mensaje=="PASS") { VARIANT vtDato;

Page 106: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

106

CString Dato; Dato = "PASS"; vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket2.SendData(vtDato); } //Establecemos conexión Cliente escritura - Scada if(mensaje==PasswordRW) { CString IP; Password=TRUE; VARIANT vtDato; CString Dato; Dato = "Conectado"; vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket2.SendData(vtDato); IP = m_socket2.GetRemoteHostIP(); CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT6); //captamos contenido edit pEdit->SetWindowText(IP); } //Si Socket1 activado enviamos temperatura actual if(Socket1==TRUE&&Password==TRUE) { if(mensaje=="Obtener") { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT1); //captamos contenido edit pEdit->GetWindowText(mensaje); vtData.vt=VT_BSTR; vtData.bstrVal=mensaje.AllocSysString(); m_socket2.SendData(vtData); } else { } } //Avisamos desconexión scada if(Socket1==FALSE) { VARIANT vtDato; CString Dato; Dato = "SCADA OFF"; vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket2.SendData(vtDato); } } //Evento perteneciente al cierre del socket 2 void CServerDlg::OnCloseWinsock2() { //AfxMessageBox ("Close2"); Password=FALSE; m_socket2.Close(); m_socket2.Listen(); CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT6); //captamos contenido edit pEdit->SetWindowText(""); } //Evento perteneciente a la modificación de la consigna del sistema void CServerDlg::OnChangeConsigna() {

Page 107: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

107

if(Socket1==TRUE) { VARIANT vtmensaje; CString mensaje; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT2); //captamos contenido edit pEdit->GetWindowText(mensaje); vtmensaje.vt=VT_BSTR; vtmensaje.bstrVal=mensaje.AllocSysString(); m_socket1.SendData(vtmensaje); } } //Evento perteneciente a la petición de conexión del socket 4 void CServerDlg::OnConnectionRequestWinsockClienteR(long requestID) { long Port; CString IP; BOOL encontrado=FALSE; //Si el servidor no esta ocupado atendemos a la petición de conexión del cliente lectura if(ServerOK==TRUE) { ServerOK=FALSE; m_socket4.Close(); IP = m_socket4.GetRemoteHostIP(); Port = m_socket4.GetRemotePort(); vtHost.vt=VT_BSTR; vtHost.bstrVal=IP.AllocSysString(); m_socket4.Accept(requestID); VARIANT vtDato; CString Dato; Dato = "Pass"; vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket4.SendData(vtDato); ServerOK=TRUE; } else { m_socket4.Close(); IP = m_socket4.GetRemoteHostIP(); Port = m_socket4.GetRemotePort(); vtHost.vt=VT_BSTR; vtHost.bstrVal=IP.AllocSysString(); m_socket4.Accept(requestID); VARIANT vtDato; CString Dato; Dato = "Servidor ocupado"; vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket4.SendData(vtDato); } } //Evento perteneciente a la recepción de datos del socket 4 void CServerDlg::OnDataArrivalWinsockClienteR(long bytesTotal) { int i=0; CString Data; BOOL encontrado=FALSE; CString strport; VARIANT vtData; VARIANT vtType; VARIANT vtMaxlen; strport="4000"; vtData.vt=VT_BSTR; vtType.vt=VT_ERROR; vtMaxlen.vt=VT_I2; vtMaxlen.iVal=(short)bytesTotal;

Page 108: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

108

CString mensaje; vtData.bstrVal=strport.AllocSysString(); vtType.bstrVal=strport.AllocSysString(); m_socket4.GetData(&vtData,vtType,vtMaxlen); mensaje=vtData.bstrVal; //Buscamos cliente lectura while((i<5) && (!encontrado)) { //Me fijo si coincide la clave. if(strcmp(m_ListaUsuarios[i]->m_strPass, mensaje)==0) { //Si coincide todo, pongo la variable bandera en TRUE encontrado=TRUE; //y tomo la edad para mostrarla. } i++; } if(encontrado) //Luego de salir del while me fijo si salió por

encontrado=TRUE { i=i-1; mensaje="Aceptado"; CString IPa; CString IP; IP = m_socket4.GetRemoteHostIP(); strcpy(m_ListaUsuarios[i]->m_strIP , IP); //Actualizamos estado del cliente if(i==0) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT11); //captamos contenido edit pEdit->SetWindowText(IP); } if(i==1) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT14); //captamos contenido edit pEdit->SetWindowText(IP); } if(i==2) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT17); //captamos contenido edit pEdit->SetWindowText(IP); } if(i==3) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT20); //captamos contenido edit pEdit->SetWindowText(IP); } if(i==4) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT23); //captamos contenido edit pEdit->SetWindowText(IP); } //CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT7); //captamos contenido edit // pEdit->GetWindowText(IPa); // pEdit->SetWindowText(IPa+" "+IP); VARIANT vtDato; vtDato.vt=VT_BSTR; vtDato.bstrVal=mensaje.AllocSysString(); SetTimer(1, 5000, NULL); //Activamos temporizador m_socket4.SendData(vtDato); //Informamos al cliente de la conexión vtHost.vt=VT_BSTR;

Page 109: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

109

vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port4.AllocSysString(); m_socket4.SetLocalPort(atoi(m_port4)); m_socket4.Listen(); //prepara para la escucha } if(!encontrado) { mensaje="PassWord Incorrecto"; VARIANT vtDato; vtDato.vt=VT_BSTR; vtDato.bstrVal=mensaje.AllocSysString(); m_socket4.SendData(vtDato); //Enviamos la cliente la información } } //Evento perteneciente al cierre del socket 4 void CServerDlg::OnCloseWinsockClienteR() { m_socket4.Close(); m_socket4.Listen(); } //Evento perteneciente al cierre del socket 3 void CServerDlg::OnCloseWinsock3() { m_socket3.Close(); m_socket3.Listen(); } //Evento perteneciente al botón validar void CServerDlg::OnValidarPSWRW() { CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT3); //captamos contenido edit pEdit2->GetWindowText(PasswordRW); AfxMessageBox ("Contraseña cliente escritura modificada"); } //Evento que es llamado al destruirse la ventana void CServerDlg::OnDestroy() { m_socket1.Close(); m_socket2.Close(); m_socket3.Close(); m_socket4.Close(); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); m_socket1.SetLocalPort(atoi(m_port)); //El proceso servidor crea ("abre") el socket servidor(socket) vtPort.bstrVal=m_port2.AllocSysString(); m_socket2.SetLocalPort(atoi(m_port2)); //El proceso servidor crea ("abre") el socket servidor(socket) vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); vtPort.bstrVal=m_port4.AllocSysString(); m_socket4.SetLocalPort(atoi(m_port4)); CDialog::OnDestroy();

Page 110: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

110

} //Evento perteneciente a la petición de conexión del socket 3 void CServerDlg::OnConnectionRequestWinsockClienteRDatos(long requestID) { //Si el servidor no esta ocupado enviamos la información al cliente de la temperatura actual if(ServerOK==TRUE) { ServerOK=FALSE; long Port; CString IP; CString Dato; m_socket3.Close(); IP = m_socket3.GetRemoteHostIP(); Port = m_socket3.GetRemotePort(); vtHost.vt=VT_BSTR; vtHost.bstrVal=IP.AllocSysString(); m_socket3.Accept(requestID); CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT1); //captamos contenido edit pEdit2->GetWindowText(Dato); VARIANT vtDato; vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket3.SendData(vtDato); } } //Evento perteneciente a la recepción de datos del socket 3 void CServerDlg::OnDataArrivalWinsockClienteRDatos(long bytesTotal) { CString strport; VARIANT vtData; VARIANT vtType; VARIANT vtMaxlen; strport="4000"; vtData.vt=VT_BSTR; vtType.vt=VT_ERROR; vtMaxlen.vt=VT_I2; vtMaxlen.iVal=(short)bytesTotal; CString mensaje; vtData.bstrVal=strport.AllocSysString(); vtType.bstrVal=strport.AllocSysString(); m_socket3.GetData(&vtData,vtType,vtMaxlen); mensaje=vtData.bstrVal; } //Evento perteneciente al botón cambiar contraseñas void CServerDlg::OnCambiarPSW() { CString PSW; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT12); pEdit->GetWindowText(PSW); strcpy(m_ListaUsuarios[0]->m_strPass , PSW); CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT15); pEdit1->GetWindowText(PSW); strcpy(m_ListaUsuarios[1]->m_strPass , PSW); CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT18);

Page 111: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

111

pEdit2->GetWindowText(PSW); strcpy(m_ListaUsuarios[2]->m_strPass , PSW); CEdit* pEdit3 = (CEdit*) GetDlgItem(IDC_EDIT21); pEdit3->GetWindowText(PSW); strcpy(m_ListaUsuarios[3]->m_strPass , PSW); CEdit* pEdit4 = (CEdit*) GetDlgItem(IDC_EDIT24); pEdit4->GetWindowText(PSW); strcpy(m_ListaUsuarios[4]->m_strPass , PSW); AfxMessageBox ("Contraseñas cambiadas"); } //Evento llamado al completarse el envio de datos por parte del socket 3 void CServerDlg::OnSendCompleteWinsockClienteRDatos() { m_socket3.Close(); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port3.AllocSysString(); m_socket3.SetLocalPort(atoi(m_port3)); m_socket3.Listen(); //prepara para la escucha ServerOK=TRUE; } //Evento perteneciente al botón habilitar/deshabilitar cliente 0 void CServerDlg::OnEnableClient0() { if(EnableClient0) { EnableClient0=FALSE; AfxMessageBox ("Cliente deshabilitado 0"); } else { EnableClient0=TRUE; AfxMessageBox ("Cliente habilitado 0"); } } //Evento perteneciente al botón habilitar/deshabilitar cliente 1 void CServerDlg::OnEnableClient1() { if(EnableClient1) { EnableClient1=FALSE; AfxMessageBox ("Cliente deshabilitado 1"); } else { EnableClient1=TRUE; AfxMessageBox ("Cliente habilitado 1"); } } //Evento perteneciente al botón habilitar/deshabilitar cliente 2 void CServerDlg::OnEnableClient2() { if(EnableClient2) { EnableClient2=FALSE; AfxMessageBox ("Cliente deshabilitado 2"); } else { EnableClient2=TRUE; AfxMessageBox ("Cliente habilitado 2");

Page 112: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

112

} } //Evento perteneciente al botón habilitar/deshabilitar cliente 3 void CServerDlg::OnEnableClient3() { if(EnableClient3) { EnableClient3=FALSE; AfxMessageBox ("Cliente deshabilitado 3"); } else { EnableClient3=TRUE; AfxMessageBox ("Cliente habilitado 3"); } } //Evento perteneciente al botón habilitar/deshabilitar cliente 4 void CServerDlg::OnEnableClient4() { if(EnableClient4) { EnableClient4=FALSE; AfxMessageBox ("Cliente deshabilitado 3"); } else { EnableClient4=TRUE; AfxMessageBox ("Cliente habilitado 3"); } } //Evento perteneciente a la petición de conexión del socket 1 void CServerDlg::OnConnectionRequestWinsockClienteRExit(long requestID) { CString IP; m_socket5.Close(); IP = m_socket5.GetRemoteHostIP(); int i=0; BOOL encontrado=FALSE; //Se busca al cliente que pide desconexión while((i<5) && (!encontrado)) { //Me fijo si coincide la clave. if(strcmp(m_ListaUsuarios[i]->m_strIP, IP)==0) { //Si coincide todo, pongo la variable bandera en TRUE encontrado=TRUE; //y tomo la edad para mostrarla. } i++; } i=i-1; strcpy(m_ListaUsuarios[i]->m_strIP , ""); if(i==0) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT11); //captamos contenido edit pEdit->SetWindowText(""); } if(i==1) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT14); //captamos contenido edit pEdit->SetWindowText("");

Page 113: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

113

} if(i==2) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT17); //captamos contenido edit pEdit->SetWindowText(""); } if(i==3) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT20); //captamos contenido edit pEdit->SetWindowText(""); } if(i==4) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT23); //captamos contenido edit pEdit->SetWindowText(""); } m_socket5.Close(); m_socket5.Listen(); //Reiniciamos socket5 } //Evento llamado al completarse el envio de datos por parte del socket 2 void CServerDlg::OnSendCompleteWinsock2() { if(Socket1!=TRUE) { m_socket2.Close(); vtPort.bstrVal=m_port2.AllocSysString(); m_socket2.SetLocalPort(atoi(m_port2)); //El proceso servidor crea (“abre”) el socket servidor(socket) //m_socket2.Bind(vtPort,vtHost); //le asigna un puerto (bind) en la máquina servidora m_socket2.Listen(); //prepara para la escucha } } //Evento perteneciente al cierre del socket 5 void CServerDlg::OnCloseWinsock5() { m_socket5.Close(); m_socket5.Listen(); }

Page 114: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

114

ServerDlg.h

// serverDlg.h : header file // //{{AFX_INCLUDES() #include "mswinsockcontrol.h" //}}AFX_INCLUDES #if !defined(AFX_SERVERDLG_H__19163570_82D7_4BBA_B402_87FB2A55328F__INCLUDED_) #define AFX_SERVERDLG_H__19163570_82D7_4BBA_B402_87FB2A55328F__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #include <stdlib.h> #include <stdio.h> #include "Usuarios.h" #define MAX_USUARIOS 5 ///////////////////////////////////////////////////////////////////////////// // CServerDlg dialog class CServerDlg : public CDialog { // Construction public: void InitSocket(); CServerDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CServerDlg) enum { IDD = IDD_SERVER_DIALOG }; CButton m_ok; BOOL Socket1; BOOL Password; BOOL EnableClient0; BOOL EnableClient1; BOOL EnableClient2; BOOL EnableClient3; BOOL EnableClient4; BOOL EnableALL; CString PasswordRW; CString LocalIP; CString m_edit1; CString m_edit2; CString m_host; CString m_port; CString m_port2; CString m_port3; CString m_port4; CString m_port5; VARIANT vtHost; VARIANT vtPort; BOOL DataSocket2; CMSWinsockControl m_socket2; CMSWinsockControl m_socket1; CMSWinsockControl m_socket3; CMSWinsockControl m_socket4; BOOL ServerOK; //Flag indicador del estado actual para recibir peticiones cliente CMSWinsockControl m_socket5; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CServerDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: HICON m_hIcon;

Page 115: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

115

CUsuarios* m_ListaUsuarios[MAX_USUARIOS]; // Generated message map functions //{{AFX_MSG(CServerDlg) virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); afx_msg void OnConnectWinsock1(); afx_msg void OnConnectionRequestWinsock1(long requestID); afx_msg void OnDataArrivalWinsock1(long bytesTotal); afx_msg void OnCloseWinsock1(); afx_msg void OnTimer(UINT nIDEvent); afx_msg void OnTactual(); afx_msg void OnConnectionRequestWinsock2(long requestID); afx_msg void OnDataArrivalWinsock2(long bytesTotal); afx_msg void OnCloseWinsock2(); afx_msg void OnEnviarres(); afx_msg void OnChangeConsigna(); afx_msg void OnConnectionRequestWinsockClienteR(long requestID); afx_msg void OnDataArrivalWinsockClienteR(long bytesTotal); afx_msg void OnCloseWinsockClienteR(); afx_msg void OnCloseWinsock3(); afx_msg void OnValidarPSWRW(); afx_msg void OnDestroy(); afx_msg void OnConnectionRequestWinsockClienteRDatos(long requestID); afx_msg void OnDataArrivalWinsockClienteRDatos(long bytesTotal); afx_msg void OnCambiarPSW(); afx_msg void OnSendCompleteWinsockClienteRDatos(); afx_msg void OnEnableClient0(); afx_msg void OnEnableClient1(); afx_msg void OnEnableClient2(); afx_msg void OnEnableClient4(); afx_msg void OnEnableClient3(); afx_msg void OnConnectionRequestWinsockClienteRExit(long requestID); afx_msg void OnSendCompleteWinsock2(); afx_msg void OnCloseWinsock5(); DECLARE_EVENTSINK_MAP() //}}AFX_MSG DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_SERVERDLG_H__19163570_82D7_4BBA_B402_87FB2A55328F__INCLUDED_)

Page 116: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

116

Usuarios.cpp // Usuarios.cpp: implementation of the CUsuarios class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" //#include "serverDlg.h" #include "Usuarios.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CUsuarios::CUsuarios() { } CUsuarios::~CUsuarios() { } CUsuarios::CUsuarios(char* strPass, char* strIP) { strcpy(m_strIP, m_strIP); strcpy(m_strPass, strPass); }

Page 117: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

117

Usuarios.h

// Usuarios.h: interface for the CUsuarios class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_USUARIOS_H__82CF0162_1C36_434C_A754_83889ED833F4__INCLUDED_) #define AFX_USUARIOS_H__82CF0162_1C36_434C_A754_83889ED833F4__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 class CUsuarios { public: char m_strPass[20]; char m_strIP[20]; CUsuarios(); CUsuarios(char* strPass, char* strIP); virtual ~CUsuarios(); }; #endif // !defined(AFX_USUARIOS_H__82CF0162_1C36_434C_A754_83889ED833F4__INCLUDED_)

Page 118: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

118

PFC.rc

//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by PFC.rc // #define IDOK2 3 #define IDOK3 4 #define IDM_ABOUTBOX 0x0010 #define IDD_ABOUTBOX 100 #define IDS_ABOUTBOX 101 #define IDD_PFC_DIALOG 102 #define IDP_SOCKETS_INIT_FAILED 103 #define IDD_SCADA 129 #define IDD_CLIENTE_LECTURA 133 #define IDD_CLIENTE_ESCRITURA 134 #define IDI_ICON 148 #define IDC_WINSOCK1 1000 #define IDC_EDIT1 1001 #define IDC_BUTTON1 1002 #define IDC_EDIT2 1003 #define IDC_EDIT3 1004 #define IDC_EDIT4 1005 #define IDC_BUTTON2 1006 #define IDC_EDIT5 1007 #define IDC_EDIT6 1008 #define IDC_EDIT7 1009 #define IDC_EDIT8 1010 #define IDC_EDIT14 1011 #define IDC_BUTTON5 1011 #define IDC_EDIT9 1012 #define IDC_EDIT10 1013 #define IDC_BUTTON4 1014 #define IDC_BUTTON3 1015 #define IDC_EDIT11 1016 #define IDC_EDIT12 1017 #define IDC_EDIT13 1018 #define IDC_BUTTON6 1019 #define IDC_WINSOCK2 1020 #define IDC_WINSOCK3 1021 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 149 #define _APS_NEXT_COMMAND_VALUE 32771 #define _APS_NEXT_CONTROL_VALUE 1022 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif

Page 119: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

119

PFC.cpp

// PFC.cpp : Defines the class behaviors for the application. // #include "stdafx.h" #include "PFC.h" #include "PFCDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CPFCApp BEGIN_MESSAGE_MAP(CPFCApp, CWinApp) //{{AFX_MSG_MAP(CPFCApp) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG ON_COMMAND(ID_HELP, CWinApp::OnHelp) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CPFCApp construction CPFCApp::CPFCApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance } ///////////////////////////////////////////////////////////////////////////// // The one and only CPFCApp object CPFCApp theApp; ///////////////////////////////////////////////////////////////////////////// // CPFCApp initialization BOOL CPFCApp::InitInstance() { if (!AfxSocketInit()) { AfxMessageBox(IDP_SOCKETS_INIT_FAILED); return FALSE; } AfxEnableControlContainer(); // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need. #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif CPFCDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) {

Page 120: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

120

// TODO: Place code here to handle when the dialog is // dismissed with Cancel } // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; }

Page 121: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

121

PFC.h

// PFC.h : main header file for the PFC application // #if !defined(AFX_PFC_H__56431A0E_2054_44D7_B064_8031C28BF07D__INCLUDED_) #define AFX_PFC_H__56431A0E_2054_44D7_B064_8031C28BF07D__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #ifndef __AFXWIN_H__ #error include 'stdafx.h' before including this file for PCH #endif #include "resource.h" // main symbols ///////////////////////////////////////////////////////////////////////////// // CPFCApp: // See PFC.cpp for the implementation of this class // class CPFCApp : public CWinApp { public: CPFCApp(); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CPFCApp) public: virtual BOOL InitInstance(); //}}AFX_VIRTUAL // Implementation //{{AFX_MSG(CPFCApp) // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_PFC_H__56431A0E_2054_44D7_B064_8031C28BF07D__INCLUDED_)

Page 122: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

122

Scada.cpp

// Scada.cpp : implementation file // #include "stdafx.h" #include "PFC.h" #include "Scada.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CScada dialog CScada::CScada(CWnd* pParent /*=NULL*/) : CDialog(CScada::IDD, pParent) { //{{AFX_DATA_INIT(CScada) //}}AFX_DATA_INIT } void CScada::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CScada) DDX_Control(pDX, IDC_WINSOCK1, m_socket1); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CScada, CDialog) //{{AFX_MSG_MAP(CScada) ON_WM_TIMER() ON_BN_CLICKED(IDC_BUTTON1, OnEnviarConsignaScada) ON_EN_CHANGE(IDC_EDIT1, OnChangeConsignaScada) ON_BN_CLICKED(IDC_BUTTON2, OnConectar) ON_BN_CLICKED(IDC_BUTTON4, OnActualizar) ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CScada message handlers BOOL CScada::OnInitDialog() { CDialog::OnInitDialog(); //Inicializamos variables del sistema y socket m_host = "127.0.0.1"; m_port = "888"; CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT6); pEdit1->SetWindowText(m_host); CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT7); pEdit2->SetWindowText(m_port); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); m_socket1.SetRemotePort(atoi(m_port)); m_socket1.SetRemoteHost(m_host);

Page 123: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

123

Consigna=23; Remote=FALSE; CEdit* pEdit3 = (CEdit*) GetDlgItem(IDC_EDIT2); pEdit3->SetWindowText("23"); LocalIP = m_socket1.GetLocalIP(); CEdit* pEdit4 = (CEdit*) GetDlgItem(IDC_EDIT8); pEdit4->SetWindowText(LocalIP); SetTimer(1, 500, NULL); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } BEGIN_EVENTSINK_MAP(CScada, CDialog) //{{AFX_EVENTSINK_MAP(CScada) ON_EVENT(CScada, IDC_WINSOCK1, 1 /* Connect */, OnConnectWinsock1, VTS_NONE) ON_EVENT(CScada, IDC_WINSOCK1, 0 /* DataArrival */, OnDataArrivalWinsock1, VTS_I4) //}}AFX_EVENTSINK_MAP END_EVENTSINK_MAP() //Evento perteneciente a la conexión del socket void CScada::OnConnectWinsock1() { Remote=TRUE; } //Evento perteneciente al temporizador void CScada::OnTimer(UINT nIDEvent) { short estado; estado=m_socket1.GetState(); CConvertirEstado m_convertirEstado; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->SetWindowText(m_convertirEstado.ConvertirEstado(estado)); /*if(estado!=7) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->SetWindowText("OFF"); }*/ if (estado == 7) { OnEnviar(); int PreConsigna; CString RemoteConsigna; CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT5); pEdit1->GetWindowText(RemoteConsigna); if (RemoteConsigna!="") { PreConsigna = atoi( RemoteConsigna ); if(PreConsigna!=0) { Consigna=PreConsigna; //Actualizamos consigna } } } else { Remote=FALSE; } int TA; CString Tact; CString Data; CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT2); pEdit2->GetWindowText(Tact); ////Simulación Proceso industrial///// TA = atoi( Tact ); if (TA!=Consigna||TA!=23)

Page 124: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

124

{ if (TA>Consigna) { TA=TA-1; } if (TA<Consigna) { TA=TA+1; } } char buffer[20]; _itoa( TA, buffer, 10 ); Data=buffer; ///////////////////////////////////// CEdit* pEdit3 = (CEdit*) GetDlgItem(IDC_EDIT2); pEdit3->SetWindowText(Data); //Se muestra por pantalla la temperatura actual CDialog::OnTimer(nIDEvent); } //Evento perteneciente al botón enviar void CScada::OnEnviarConsignaScada() { if(Remote==FALSE) { if(ConsignaSCADA<23||ConsignaSCADA>281) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT3); pEdit->SetWindowText("Valor de consigna no valido"); } else { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT3); pEdit->SetWindowText("Valor de consigna valido"); Consigna = ConsignaSCADA; } } else { AfxMessageBox ("El control Remoto esta activado"); } } //Evento llamado con la variación de la ventana de texto consigna void CScada::OnChangeConsignaScada() { CString ConsignaScada; CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT1); pEdit1->GetWindowText(ConsignaScada); ConsignaSCADA = atoi( ConsignaScada ); if(Remote==FALSE) { if(ConsignaSCADA<23||ConsignaSCADA>281) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT3); pEdit->SetWindowText("Valor de consigna no valido"); CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT2); pEdit1->GetWindowText(ConsignaScada); ConsignaSCADA = atoi ( ConsignaScada ); } else { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT3);

Page 125: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

125

pEdit->SetWindowText("Valor de consigna valido"); } } else { } } //Evento perteneciente al boton conectar void CScada::OnConectar() { CString estado; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->GetWindowText(estado); if (estado == "Conectado") { VARIANT vtDato; CString Dato; Dato = "Desconectar"; vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket1.SendData(vtDato); AfxMessageBox ("sistema desconectado"); } else if (estado =! "Conectado") { m_socket1.Close(); m_socket1.Connect(vtHost,vtPort); } } //Se actualizan parametros de configuración de puertos y IP del servidor void CScada::OnActualizar() { CString estado; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->GetWindowText(estado); if (estado != "Desconectado"&& estado != "Cerrado") { AfxMessageBox ("El sistema ya esta conectado con la IP establecida. Para establecer una nueva dirección debe reiniciar el programa"); } else { CString Host; CString Host1; CString Host2; CString Host3; CString Port; CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT9); pEdit1->GetWindowText(Host); Host=Host+"."; CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT10); pEdit2->GetWindowText(Host1); Host1=Host+Host1+"."; CEdit* pEdit3 = (CEdit*) GetDlgItem(IDC_EDIT11); pEdit3->GetWindowText(Host2); Host2=Host1+Host2+"."; CEdit* pEdit4 = (CEdit*) GetDlgItem(IDC_EDIT12); pEdit4->GetWindowText(Host3); Host3=Host2+Host3; CEdit* pEdit5 = (CEdit*) GetDlgItem(IDC_EDIT13); pEdit5->GetWindowText(Port); m_host = Host3; m_port = Port;

Page 126: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

126

CEdit* pEdit6 = (CEdit*) GetDlgItem(IDC_EDIT6); pEdit6->SetWindowText(m_host); CEdit* pEdit7 = (CEdit*) GetDlgItem(IDC_EDIT7); pEdit7->SetWindowText(m_port); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); m_socket1.SetRemotePort(atoi(m_port)); m_socket1.SetRemoteHost(m_host); } } //Evento llamado cuando se produce la destrucción de la ventana void CScada::OnDestroy() { m_socket1.Close(); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); m_socket1.SetRemotePort(atoi(m_port)); m_socket1.SetRemoteHost(m_host); CDialog::OnDestroy(); } //Evento perteneciente a la llegada de datos del socket void CScada::OnDataArrivalWinsock1(long bytesTotal) { CString strport; VARIANT vtData; VARIANT vtType; VARIANT vtMaxlen; strport="4000"; vtData.vt=VT_BSTR; vtType.vt=VT_ERROR; vtMaxlen.vt=VT_I2; vtMaxlen.iVal=(short)bytesTotal; CString mensaje; vtData.bstrVal=strport.AllocSysString(); vtType.bstrVal=strport.AllocSysString(); m_socket1.GetData(&vtData,vtType,vtMaxlen); mensaje=vtData.bstrVal; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT5); pEdit->SetWindowText(mensaje); //Introducimos por pantalla consigna remota } //Envio de la temperatura actual al servidor void CScada::OnEnviar() { VARIANT vtDato;

CString Dato; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT2); //captamos contenido edit

Page 127: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

127

pEdit->GetWindowText(Dato); vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket1.SendData(vtDato); }

Page 128: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

128

Scada.h //{{AFX_INCLUDES() #include "mswinsockcontrol.h" //}}AFX_INCLUDES #if !defined(AFX_SCADA_H__683A305E_4720_4EBE_BE59_D291D9905FB7__INCLUDED_) #define AFX_SCADA_H__683A305E_4720_4EBE_BE59_D291D9905FB7__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #include "mswinsockcontrol.h" #include "ConvertirEstado.h" // Scada.h : header file // ///////////////////////////////////////////////////////////////////////////// // CScada dialog class CScada : public CDialog { // Construction public: CScada(CWnd* pParent = NULL); // standard constructor CString m_host; CString m_port; CString LocalIP; VARIANT vtHost; VARIANT vtPort; int Consigna; int ConsignaSCADA; BOOL Remote; //CMSWinsockControl m_socket1; // Dialog Data //{{AFX_DATA(CScada) enum { IDD = IDD_SCADA }; CMSWinsockControl m_socket1; //}}AFX_DATA // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CScada) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(CScada) virtual BOOL OnInitDialog(); afx_msg void OnConnectWinsock1(); afx_msg void OnTimer(UINT nIDEvent); afx_msg void OnEnviarConsignaScada(); afx_msg void OnChangeConsignaScada(); afx_msg void OnConectar(); afx_msg void OnEnviar(); afx_msg void OnActualizar(); afx_msg void OnDestroy(); afx_msg void OnDataArrivalWinsock1(long bytesTotal); DECLARE_EVENTSINK_MAP() //}}AFX_MSG DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_SCADA_H__683A305E_4720_4EBE_BE59_D291D9905FB7__INCLUDED_)

Page 129: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

129

ConvertirEstado.cpp

// ConvertirEstado.cpp : implementation file // #include "stdafx.h" #include "PFC.h" #include "ConvertirEstado.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif /////////////////////////////////////////////////////////////////// // CConvertirEstado CConvertirEstado::CConvertirEstado() { } CConvertirEstado::~CConvertirEstado() { } CString CConvertirEstado::ConvertirEstado(int Estado) { switch (Estado) { case 0: return "Cerrado"; break; case 1: return "Abierto"; break; case 2: return "Escuchando"; break; case 3: return "Conexión pendiente de abrir"; break; case 4: return "Resolviendo Host"; break; case 5: return "Host Resuelto"; break; case 6: return "Conectando"; break; case 7: return "Conectado"; break; case 8: return "Peer esta cerrando la conexión"; break; case 9: return "Error"; break; case 10: return "Invalido"; break; default: return ""; break; } } BEGIN_MESSAGE_MAP(CConvertirEstado, CWnd) //{{AFX_MSG_MAP(CConvertirEstado) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP END_MESSAGE_MAP()

Page 130: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

130

ConvertirEstado.h

#if !defined(AFX_CONVERTIRESTADO_H__6D8B783D_F4FA_4EB0_B6B0_21636F95514C__INCLUDED_) #define AFX_CONVERTIRESTADO_H__6D8B783D_F4FA_4EB0_B6B0_21636F95514C__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 // ConvertirEstado.h : header file // ///////////////////////////////////////////////////////////////////////////// // CConvertirEstado window class CConvertirEstado : public CWnd { // Construction public: CConvertirEstado(); CString ConvertirEstado(int estado); // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CConvertirEstado) //}}AFX_VIRTUAL // Implementation public: virtual ~CConvertirEstado(); // Generated message map functions protected: //{{AFX_MSG(CConvertirEstado) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_CONVERTIRESTADO_H__6D8B783D_F4FA_4EB0_B6B0_21636F95514C__INCLUDED_)

Page 131: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

131

CEscritura.cpp

// CEscritura.cpp : implementation file // #include "stdafx.h" #include "PFC.h" #include "CEscritura.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CCEscritura dialog CCEscritura::CCEscritura(CWnd* pParent /*=NULL*/) : CDialog(CCEscritura::IDD, pParent) { //{{AFX_DATA_INIT(CCEscritura) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT } void CCEscritura::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CCEscritura) DDX_Control(pDX, IDC_WINSOCK1, m_socket1); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CCEscritura, CDialog) //{{AFX_MSG_MAP(CCEscritura) ON_WM_TIMER() ON_BN_CLICKED(IDC_BUTTON2, OnConectar) ON_BN_CLICKED(IDC_BUTTON4, OnActualizar) ON_BN_CLICKED(IDC_BUTTON3, OnConfirmarPassword) ON_BN_CLICKED(IDC_BUTTON5, OnObtener) ON_BN_CLICKED(IDC_BUTTON1, OnEnviar) ON_EN_CHANGE(IDC_EDIT1, OnChangeConsigna) ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CCEscritura message handlers BOOL CCEscritura::OnInitDialog() { CDialog::OnInitDialog(); //Inicializamos variables del sistema y socket short estado; m_host = "127.0.0.1"; m_port = "889"; CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT6); pEdit1->SetWindowText(m_host); CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT7); pEdit2->SetWindowText(m_port); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port));

Page 132: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

132

//m_socket1.SetProtocol(0); m_socket1.SetRemotePort(atoi(m_port)); m_socket1.SetRemoteHost(m_host); Consigna=0; Remote=FALSE; CEdit* pEdit3 = (CEdit*) GetDlgItem(IDC_EDIT2); pEdit3->SetWindowText("OFF"); LocalIP = m_socket1.GetLocalIP(); CEdit* pEdit4 = (CEdit*) GetDlgItem(IDC_EDIT8); pEdit4->SetWindowText(LocalIP); estado=m_socket1.GetState(); CConvertirEstado m_convertirEstado; CEdit* pEdit5 = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit5->SetWindowText(m_convertirEstado.ConvertirEstado(estado)); //Mostramos estado de conexión por pantalla SetTimer(1, 500, NULL); //Activación sel temporizador return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } //Evento perteneciente al temporizador void CCEscritura::OnTimer(UINT nIDEvent) { if (!PASS) { short estado; estado=m_socket1.GetState(); CConvertirEstado m_convertirEstado; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->SetWindowText(m_convertirEstado.ConvertirEstado(estado)); //Mostramos estado de conexión por pantalla } CDialog::OnTimer(nIDEvent); } BEGIN_EVENTSINK_MAP(CCEscritura, CDialog) //{{AFX_EVENTSINK_MAP(CCEscritura) ON_EVENT(CCEscritura, IDC_WINSOCK1, 1 /* Connect */, OnConnectWinsock1, VTS_NONE) ON_EVENT(CCEscritura, IDC_WINSOCK1, 0 /* DataArrival */, OnDataArrivalWinsock1, VTS_I4) //}}AFX_EVENTSINK_MAP END_EVENTSINK_MAP() //Evento perteneciente a la conexión del socket void CCEscritura::OnConnectWinsock1() { VARIANT vtDato; CString Dato; Dato = "PASS"; vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket1.SendData(vtDato); //Solicitamos permiso de introducción de contraseña al servidor } //Evento perteneciente al boton conectar void CCEscritura::OnConectar() { CString estado; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->GetWindowText(estado); //Captamos el estado de la conexión con el servidor if (estado == "Conectado") { AfxMessageBox ("El sistema ya esta conectado"); } else if (estado =! "Conectado")

Page 133: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

133

{ PASS=TRUE; m_socket1.Close(); m_socket1.Connect(vtHost,vtPort); //Si el sistema esta desconectado, conectamos con el servidor } } //Evento perteneciente al boton conectar void CCEscritura::OnActualizar() { CString estado; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->GetWindowText(estado); //Captamos el estado de la conexión con el servidor if (estado != "Desconectado"&& estado != "Cerrado") { AfxMessageBox ("El sistema ya esta conectado con la IP establecida. Para establecer una nueva dirección debe reiniciar el programa"); } else { CString Host; CString Host1; CString Host2; CString Host3; CString Port; CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT9); pEdit1->GetWindowText(Host); Host=Host+"."; CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT10); pEdit2->GetWindowText(Host1); Host1=Host+Host1+"."; CEdit* pEdit3 = (CEdit*) GetDlgItem(IDC_EDIT11); pEdit3->GetWindowText(Host2); Host2=Host1+Host2+"."; CEdit* pEdit4 = (CEdit*) GetDlgItem(IDC_EDIT12); pEdit4->GetWindowText(Host3); Host3=Host2+Host3; CEdit* pEdit5 = (CEdit*) GetDlgItem(IDC_EDIT13); pEdit5->GetWindowText(Port); m_host = Host3; m_port = Port; CEdit* pEdit6 = (CEdit*) GetDlgItem(IDC_EDIT6); pEdit6->SetWindowText(m_host); CEdit* pEdit7 = (CEdit*) GetDlgItem(IDC_EDIT7); pEdit7->SetWindowText(m_port); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); m_socket1.SetRemotePort(atoi(m_port)); m_socket1.SetRemoteHost(m_host); } } //Evento perteneciente a la llegada de datos del socket void CCEscritura::OnDataArrivalWinsock1(long bytesTotal) { CString strport; VARIANT vtData; VARIANT vtType; VARIANT vtMaxlen;

Page 134: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

134

strport="4000"; vtData.vt=VT_BSTR; vtType.vt=VT_ERROR; vtMaxlen.vt=VT_I2; vtMaxlen.iVal=(short)bytesTotal; CString mensaje; vtData.bstrVal=strport.AllocSysString(); vtType.bstrVal=strport.AllocSysString(); m_socket1.GetData(&vtData,vtType,vtMaxlen); mensaje=vtData.bstrVal; //Introducimos temperatura actual en pantalla if(mensaje!="SCADA OFF"&&mensaje!="PASS"&&mensaje!="Pass"&&mensaje!="Conectado"&&mensaje!="PASSSCADA OFF"&&mensaje!="SCADA OFFPASSSCADA OFF") { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->SetWindowText("Conectado"); CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT2); pEdit1->SetWindowText(mensaje); } //Avisamos por pantalla de la introducción de contraseña if(mensaje=="PASS") { PASS=TRUE; AfxMessageBox ("Confirmar Password"); } //Avisamos por pantalla de la introducción de contraseña if(mensaje=="Conectado") { AfxMessageBox ("Password correcto"); CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit1->SetWindowText("Conectado"); PASS=FALSE; } //Avisamos de la desconexión del scada if(mensaje=="SCADA OFF") { PASS=TRUE; AfxMessageBox ("Control Remoto SCADA desactivado"); m_socket1.Close(); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); m_socket1.SetRemotePort(atoi(m_port)); m_socket1.SetRemoteHost(m_host); CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit1->SetWindowText("Desconectado"); } } //Evento perteneciente al boton confirmar password void CCEscritura::OnConfirmarPassword() { if(PASS==TRUE) { VARIANT vtDato;

Page 135: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

135

CString Dato; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT5); pEdit->GetWindowText(Dato); vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket1.SendData(vtDato); } } //Evento perteneciente al botón obtener void CCEscritura::OnObtener() { CString estado; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->GetWindowText(estado); if (estado == "Conectado") { VARIANT vtDato; CString Dato; Dato = "Obtener"; vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket1.SendData(vtDato); } else if (estado =! "Conectado") { AfxMessageBox ("El sistema no esta conectado"); } } //Evento perteneciente al botón enviar void CCEscritura::OnEnviar() { CString estado; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->GetWindowText(estado); if (estado == "Conectado") { VARIANT vtDato; CString Dato; char buffer[20]; _itoa( Consigna, buffer, 10 ); Dato=buffer; vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); if(Dato!="0") { m_socket1.SendData(vtDato); } } else if (estado =! "Conectado") { AfxMessageBox ("El sistema no esta conectado"); } } //Evento llamado con la variación de la ventana de texto consigna void CCEscritura::OnChangeConsigna() { int PreConsigna; CString Dato; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT1); pEdit->GetWindowText(Dato); PreConsigna = atoi( Dato ); if(PreConsigna<23||PreConsigna>180) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT3); pEdit->SetWindowText("Valor de consigna no valido"); } else { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT3);

Page 136: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

136

pEdit->SetWindowText("Valor de consigna valido"); Consigna = atoi( Dato ); } } //Evento llamado cuando se produce la destrucción de la ventana void CCEscritura::OnDestroy() { m_socket1.Close(); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); m_socket1.SetRemotePort(atoi(m_port)); m_socket1.SetRemoteHost(m_host); CDialog::OnDestroy(); }

Page 137: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

137

CEscritura.h

//{{AFX_INCLUDES() #include "mswinsockcontrol1.h" //}}AFX_INCLUDES #if !defined(AFX_CESCRITURA_H__D8EBDECD_F8A6_4AD4_B241_E0B58BE3F967__INCLUDED_) #define AFX_CESCRITURA_H__D8EBDECD_F8A6_4AD4_B241_E0B58BE3F967__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #include "mswinsockcontrol.h" #include "ConvertirEstado.h" // CEscritura.h : header file // ///////////////////////////////////////////////////////////////////////////// // CCEscritura dialog class CCEscritura : public CDialog { // Construction public: CCEscritura(CWnd* pParent = NULL); // standard constructor CString m_host; CString m_port; CString LocalIP; VARIANT vtHost; VARIANT vtPort; int Consigna; int ConsignaSCADA; BOOL PASS; BOOL Remote; // Dialog Data //{{AFX_DATA(CCEscritura) enum { IDD = IDD_CLIENTE_ESCRITURA }; CMSWinsockControl1 m_socket1; //}}AFX_DATA // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CCEscritura) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(CCEscritura) virtual BOOL OnInitDialog(); afx_msg void OnTimer(UINT nIDEvent); afx_msg void OnConnectWinsock1(); afx_msg void OnConectar(); afx_msg void OnActualizar(); afx_msg void OnDataArrivalWinsock1(long bytesTotal); afx_msg void OnConfirmarPassword(); afx_msg void OnObtener(); afx_msg void OnEnviar(); afx_msg void OnChangeConsigna(); afx_msg void OnDestroy(); DECLARE_EVENTSINK_MAP() //}}AFX_MSG DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_CESCRITURA_H__D8EBDECD_F8A6_4AD4_B241_E0B58BE3F967__INCLUDED_)

Page 138: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

138

CLectura.cpp

// CLectura.cpp : implementation file // #include "stdafx.h" #include "PFC.h" #include "CLectura.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CCLectura dialog CCLectura::CCLectura(CWnd* pParent /*=NULL*/) : CDialog(CCLectura::IDD, pParent) { //{{AFX_DATA_INIT(CCLectura) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT } void CCLectura::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CCLectura) DDX_Control(pDX, IDC_WINSOCK1, m_socket1); DDX_Control(pDX, IDC_WINSOCK2, m_socket2); DDX_Control(pDX, IDC_WINSOCK3, m_socket3); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CCLectura, CDialog) //{{AFX_MSG_MAP(CCLectura) ON_WM_TIMER() ON_BN_CLICKED(IDC_BUTTON4, OnActualizar) ON_BN_CLICKED(IDC_BUTTON2, OnConectar) ON_BN_CLICKED(IDC_BUTTON3, OnConfirmarPassword) ON_BN_CLICKED(IDC_BUTTON6, OnObtener) ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CCLectura message handlers BOOL CCLectura::OnInitDialog() { CDialog::OnInitDialog(); //Inicializamos variables del sistema y socket short estado; m_host = "127.0.0.1"; m_port = "890"; m_portR = "891"; m_portExit = "892"; PASS = FALSE; Remote = FALSE; Obtener = FALSE; CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT6); pEdit1->SetWindowText(m_host); CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT7); pEdit2->SetWindowText(m_port);

Page 139: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

139

vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); m_socket1.SetRemotePort(atoi(m_port)); m_socket1.SetRemoteHost(m_host); vtHostR.vt=VT_BSTR; vtPortR.vt=VT_BSTR; vtHostR.bstrVal=m_host.AllocSysString(); vtPortR.bstrVal=m_portR.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); m_socket2.SetRemotePort(atoi(m_portR)); m_socket2.SetRemoteHost(m_host); vtHostExit.vt=VT_BSTR; vtPortExit.vt=VT_BSTR; vtHostExit.bstrVal=m_host.AllocSysString(); vtPortExit.bstrVal=m_portExit.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); m_socket3.SetRemotePort(atoi(m_portExit)); m_socket3.SetRemoteHost(m_host); Consigna=23; Remote=FALSE; CEdit* pEdit3 = (CEdit*) GetDlgItem(IDC_EDIT2); pEdit3->SetWindowText("OFF"); LocalIP = m_socket1.GetLocalIP(); CEdit* pEdit4 = (CEdit*) GetDlgItem(IDC_EDIT8); pEdit4->SetWindowText(LocalIP); estado=m_socket1.GetState(); CConvertirEstado m_convertirEstado; CEdit* pEdit5 = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit5->SetWindowText(m_convertirEstado.ConvertirEstado(estado)); CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->SetWindowText("Desconectado"); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } //Evento perteneciente al temporizador void CCLectura::OnTimer(UINT nIDEvent) { if(!Remote) { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->SetWindowText("Error"); Obtener=FALSE; } else if(Remote) { KillTimer(0); Remote=FALSE; } CDialog::OnTimer(nIDEvent); } //Se actualizan parametros de configuración de puertos y IP del servidor void CCLectura::OnActualizar() { CString estado; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->GetWindowText(estado);

Page 140: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

140

if (estado != "Desconectado") { AfxMessageBox ("El sistema ya esta conectado con la IP establecida. Para establecer una nueva dirección debe reiniciar el programa"); } else if (estado == "Desconectado") { CString Host; CString Host1; CString Host2; CString Host3; CString Port; CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT9); pEdit1->GetWindowText(Host); Host=Host+"."; CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT10); pEdit2->GetWindowText(Host1); Host1=Host+Host1+"."; CEdit* pEdit3 = (CEdit*) GetDlgItem(IDC_EDIT11); pEdit3->GetWindowText(Host2); Host2=Host1+Host2+"."; CEdit* pEdit4 = (CEdit*) GetDlgItem(IDC_EDIT12); pEdit4->GetWindowText(Host3); Host3=Host2+Host3; CEdit* pEdit5 = (CEdit*) GetDlgItem(IDC_EDIT13); pEdit5->GetWindowText(Port); m_host = Host3; m_port = Port; CEdit* pEdit6 = (CEdit*) GetDlgItem(IDC_EDIT6); pEdit6->SetWindowText(m_host); CEdit* pEdit7 = (CEdit*) GetDlgItem(IDC_EDIT7); pEdit7->SetWindowText(m_port); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); m_socket1.SetRemotePort(atoi(m_port)); m_socket1.SetRemoteHost(m_host); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_portR.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); m_socket2.SetRemotePort(atoi(m_portR)); m_socket2.SetRemoteHost(m_host); } } //Evento perteneciente al boton conectar void CCLectura::OnConectar() { CString estado; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->GetWindowText(estado); //Captamos el estado de la conexión con el servidor if (estado == "Conectado") { AfxMessageBox ("El sistema ya esta conectado"); } else if (estado =! "Conectado") {

Page 141: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

141

m_socket1.Close(); m_socket1.Connect(vtHost,vtPort); //Si el sistema esta desconectado, conectamos con el servidor SetTimer(1, 10000, NULL); //Activamos temporizador } } BEGIN_EVENTSINK_MAP(CCLectura, CDialog) //{{AFX_EVENTSINK_MAP(CCLectura) ON_EVENT(CCLectura, IDC_WINSOCK1, 1 /* Connect */, OnConnectWinsock1, VTS_NONE) ON_EVENT(CCLectura, IDC_WINSOCK1, 0 /* DataArrival */, OnDataArrivalWinsock1, VTS_I4) ON_EVENT(CCLectura, IDC_WINSOCK2, 1 /* Connect */, OnConnectWinsock2, VTS_NONE) ON_EVENT(CCLectura, IDC_WINSOCK2, 0 /* DataArrival */, OnDataArrivalWinsock2, VTS_I4) ON_EVENT(CCLectura, IDC_WINSOCK2, 5 /* Close */, OnCloseWinsock2, VTS_NONE) //}}AFX_EVENTSINK_MAP END_EVENTSINK_MAP() //Evento perteneciente a la conexión del socket1 void CCLectura::OnConnectWinsock1() { Remote = TRUE; PASS = TRUE; AfxMessageBox ("Introducir Password"); } //Evento perteneciente al boton confirmar password void CCLectura::OnConfirmarPassword() { if (PASS) { VARIANT vtDato; CString Dato; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT5); pEdit->GetWindowText(Dato); vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket1.SendData(vtDato); } } //Evento perteneciente a la llegada de datos del socket1 void CCLectura::OnDataArrivalWinsock1(long bytesTotal) { CString strport; VARIANT vtData; VARIANT vtType; VARIANT vtMaxlen; strport="4000"; vtData.vt=VT_BSTR; vtType.vt=VT_ERROR; vtMaxlen.vt=VT_I2; vtMaxlen.iVal=(short)bytesTotal; CString mensaje; vtData.bstrVal=strport.AllocSysString(); vtType.bstrVal=strport.AllocSysString(); m_socket1.GetData(&vtData,vtType,vtMaxlen); mensaje=vtData.bstrVal; //AfxMessageBox (mensaje); if(mensaje=="Aceptado") { CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->SetWindowText("Conectado"); PASS = FALSE;

Page 142: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

142

m_socket1.Close(); vtHost .vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); m_socket1.SetRemotePort(atoi(m_portR)); m_socket1.SetRemoteHost(m_host); //Una vez conectado se deja libre socket1 para que otro cliente pueda conectarse con el servidor } } //Evento perteneciente al botón obtener void CCLectura::OnObtener() { CString estado; CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4); pEdit->GetWindowText(estado); if(estado=="Conectado") { //Si flag obtener desactivado, conectamos con servidor if(Obtener==FALSE) { Obtener=TRUE; SetTimer(1, 10000, NULL); m_socket2.Close(); m_socket2.Connect(vtHostR,vtPortR); } } } //Evento perteneciente a la conexión del socket2 void CCLectura::OnConnectWinsock2() { Remote = TRUE; VARIANT vtDato; CString Dato; Dato = "Obtener"; vtDato.vt=VT_BSTR; vtDato.bstrVal=Dato.AllocSysString(); m_socket2.SendData(vtDato); //AfxMessageBox ("Obtener"); } //Evento perteneciente a la llegada de datos del socket2 void CCLectura::OnDataArrivalWinsock2(long bytesTotal) { CString strport; VARIANT vtData; VARIANT vtType; VARIANT vtMaxlen; strport="4000"; vtData.vt=VT_BSTR; vtType.vt=VT_ERROR; vtMaxlen.vt=VT_I2; vtMaxlen.iVal=(short)bytesTotal; CString mensaje; vtData.bstrVal=strport.AllocSysString(); vtType.bstrVal=strport.AllocSysString(); m_socket2.GetData(&vtData,vtType,vtMaxlen); mensaje=vtData.bstrVal;

Page 143: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

143

CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT2); pEdit->SetWindowText(mensaje); //Se muestra por pantalla la temperatura actual Obtener=FALSE; } //Evento llamado cuando se produce la destrucción de la ventana void CCLectura::OnDestroy() { m_socket1.Close(); vtHost.vt=VT_BSTR; vtPort.vt=VT_BSTR; vtHost.bstrVal=m_host.AllocSysString(); vtPort.bstrVal=m_port.AllocSysString(); //m_socket1.SetLocalPort(atoi(m_port)); //m_socket1.SetProtocol(0); m_socket1.SetRemotePort(atoi(m_port)); m_socket1.SetRemoteHost(m_host); m_socket3.Close(); m_socket3.Connect(vtHostExit,vtPortExit); //Conectamos con servidor para informar de la desconexión del cliente AfxMessageBox ("Si el sistema esta conectado con el servidor va a ser desconectado"); CDialog::OnDestroy(); }

Page 144: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

144

Clectura.h //{{AFX_INCLUDES() #include "mswinsockcontrol1.h" //}}AFX_INCLUDES #if !defined(AFX_CLECTURA_H__B61C1F2C_1840_4BA6_B788_E22CDD012BFA__INCLUDED_) #define AFX_CLECTURA_H__B61C1F2C_1840_4BA6_B788_E22CDD012BFA__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #include "mswinsockcontrol.h" #include "ConvertirEstado.h" // CLectura.h : header file // ///////////////////////////////////////////////////////////////////////////// // CCLectura dialog class CCLectura : public CDialog { // Construction public: CCLectura(CWnd* pParent = NULL); // standard constructor CString m_host; CString m_port; CString m_portR; CString m_portExit; CString LocalIP; VARIANT vtHost; VARIANT vtPort; VARIANT vtHostR; VARIANT vtPortR; VARIANT vtHostExit; VARIANT vtPortExit; int Consigna; int ConsignaSCADA; BOOL Remote; BOOL PASS; BOOL Obtener; // Dialog Data //{{AFX_DATA(CCLectura) enum { IDD = IDD_CLIENTE_LECTURA }; CMSWinsockControl1 m_socket1; CMSWinsockControl1 m_socket2; CMSWinsockControl1 m_socket3; //}}AFX_DATA // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CCLectura) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(CCLectura) virtual BOOL OnInitDialog(); afx_msg void OnTimer(UINT nIDEvent); afx_msg void OnActualizar(); afx_msg void OnConectar(); afx_msg void OnConnectWinsock1();

Page 145: APLICACIÓN SCADA COMUNICACIÓN TCP/IPdeeea.urv.cat/public/PROPOSTES/pub/pdf/1118pub.pdf · - Mediante tablas de rutas estáticas o dinámicas Direccionamiento IP

                       APLICACIÓN SCADA BASADA EN COMUNICACIÓN TCP/IP                                               ESTEVE GRAU PINA       

145

afx_msg void OnConfirmarPassword(); afx_msg void OnDataArrivalWinsock1(long bytesTotal); afx_msg void OnObtener(); afx_msg void OnConnectWinsock2(); afx_msg void OnDataArrivalWinsock2(long bytesTotal); afx_msg void OnDestroy(); afx_msg void OnCloseWinsock2(); DECLARE_EVENTSINK_MAP() //}}AFX_MSG DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_CLECTURA_H__B61C1F2C_1840_4BA6_B788_E22CDD012BFA__INCLUDED_)