Vous êtes sur la page 1sur 145

APLICACIN SCADA BASADA EN

COMUNICACIN TCP/IP

INGENIERA TCNICA INDUSTRIAL ESPECIALIDAD ELECTRNICA INDUSTRIAL

AUTOR: Esteve Grau Pina

PONENTE: Ernest Gil Dolcet

FECHA: Junio 2009


APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

MEMORIA

DESCRIPTIVA

2
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

NDICE
Objetivos del proyecto ___________________________________________ 4
Configuracin de la conexin______________________________________ 5
Fundamentos arquitectura TCP/IP___________________________________ 8
Introduccin 11
El Protocolo Internet (Internet Protocol - IP) 12
Direccionamiento IP 13
Direcciones de red y de difusin 14
Resumen de las reglas especiales de direccionamiento 15
Protocolos de Ruteo (nivel IP) 15
Protocolo de Informacin de Ruteo (RIP) 16
Protocolo SPF abierto (OSPF) 17
Protocolos de resolucin de direcciones 18
Protocolo de Asociacin de Direcciones por Rplica (RARP) 18
Mensajes de error y control en IP (ICMP) 19
Protocolo de datagrama de usuario (UDP) 20
Protocolo de control de transmisin (TCP) 22
Puertos, conexiones y puntos extremos 24
La interface socket_______________________________________________ 31
Introduccin Sockets 32
Identificacin de un socket 32
Tipos de sockets 34
Modelo de comunicacin cliente servidor 35
Proceso de conexin cliente servidor 36
Modelo de programacin 38
Byte order 39
Programacin de sockets en Windows 40
Programacin de sockets en Windows usando C++ y MFC 41
Fundamentos sobre el control MSWinsockControl______________________ 43
Diagramas de flujo_______________________________________________ 61
Introduccin 62
Aplicacin scada 63
Aplicacin cliente lectura 64
Aplicacin cliente escritura 65
Aplicacin servidor 66
Conclusiones_____________________________________________________ 68
Referencias_____________________________________________________ 71

3
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

OBJETIVOS
DEL PROYECTO

4
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

El propsito de este proyecto reside en la realizacin de una aplicacin, realizada en


Microsoft Visual C++ , que pueda realizar el control y monitorizacin remota de un
proceso industrial. Los diferentes usuarios podrn 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 conexin
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 ubicacin exterior a la planta
debern poseer de un ordenador conectado a internet y poseer una identificacin
suministrada por la empresa.
Tambin se ha contemplado la opcin de incorporar una aplicacin nica donde, a travs
de internet, se podr enviar la consigna deseada en el proceso industrial.
Las dos conexiones basadas en internet slo estarn habilitadas cuando el usuario del
ordenador donde se ubica el sistema captador de datos (SCADA) haya activado la opcin
de control remoto.
En la figura 1 se puede observar la aplicacin del proceso industrial en la cual se ha
basado este proyecto.

Figura1. Proceso industrial con aplicacin Horno

5
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

CONFIGURACIN
DE LA CONEXIN

6
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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.
Segn 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 tecnologa Internet para
compartir de forma segura cualquier informacin 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. Podra proporcionar una comunicacin
privada y exitosa en una organizacin.

Fig1.1 Ejemplo conexin intranet. 1

2. Intranet con conexin a Internet a travs 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

7
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

ayuda de un servidor proxy a Internet . En el contexto de las redes informticas, el


trmino proxy hace referencia a un programa o dispositivo que realiza una accin en
representacin de otro. Su finalidad ms habitual es la de servidor proxy, que sirve para
permitir el acceso a Internet a todos los equipos de una organizacin cuando slo se
puede disponer de un nico equipo conectado, esto es, una nica direccin IP.
Un proxy permite a otros equipos conectarse a una red de forma indirecta a travs de l.
Cuando un equipo de la red desea acceder a una informacin o recurso, es realmente el
proxy quien realiza la comunicacin y a continuacin traslada el resultado al equipo
inicial. En unos casos esto se hace as porque no es posible la comunicacin directa y en
otros casos porque el proxy aade una funcionalidad adicional, como puede ser la de
mantener los resultados obtenidos (p.ej.: una pgina web) en una cach que permita
acelerar sucesivas consultas coincidentes. Con esta denominacin general de proxy se
agrupan diversas tcnicas.

Fig1.2 Ejemplo conexin con Proxy.

8
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

3. Conexin a Internet a travs de ISP


Conectarnos telefnicamente mediante un mdem 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 ingls 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. Tambin ofrece servicios relacionados, como alojamiento web o
registro de dominios, entre otros.

Fig1.2 Ejemplo conexin a internet mediante ISP. 2

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

9
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

ARQUITECTURA
TCP/IP

10
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Introduccin
La arquitectura TCP/IP esta hoy en da ampliamente difundida, a pesar de ser una
arquitectura de facto, en lugar de ser uno de los estndares 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 expansin de la
INTERNET se ha convertido en una de las arquitecturas de redes ms difundida.
Antes de continuar, pasemos a ver la relacin 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 fsico], el nivel de
interred [Red, IP], el protocolo proveedor de servicio [Transporte, TCP o UDP] , y el
nivel de aplicacin.

11
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 informacin y la administracin
del proceso de fragmentacin de dichos datagramas.
El datagrama es la unidad de transferencia que el IP utiliza, algunas veces identificada en
forma ms especfica como datagrama Internet o datagrama IP
Las caractersticas de este protocolo son :

NO ORIENTADO A CONEXIN
- Transmisin en unidades denominadas datagramas.
- Sin correccin de errores, ni control de congestin.
- No garantiza la entrega en secuencia.

Figura 1. Estructura simplificada de un datagrama IP

12
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 verificacin para el contenido de datos del
datagrama, solamente para la informacin del encabezado.
En cuanto al ruteo (encaminamiento) este puede ser :
- Paso a paso a todos los nodos
- Mediante tablas de rutas estticas o dinmicas

Direccionamiento IP
El TCP/IP utiliza una direccin de 32 bits para identificar una mquina y la red a la cual est
conectada. Unicamente el NIC (Centro de Informacin 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 numeracin.
Hay cuatro formatos para la direccin IP, cada uno de los cuales se utiliza dependiendo del
tamao de la red. Los cuatro formatos, Clase A hasta Clase D (aunque ltimamente se ha
aadido la Clase E para un futuro) aparecen en la figura :

CLASE A

CLASE B

CLASE C

CLASE D

Conceptualmente, cada direccin 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 ms alto).

13
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Las direcciones de Clase A corresponden a redes grandes con muchas mquinas. 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 tamao intermedio, y el rango de direcciones
vara 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 slo 8 bits para la direccin local o de anfitrin (host) y 21
bits para red. Las direcciones de esta clase estn 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 multidifusin, cuando se quiere
una difusin general a ms 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 utilizacin 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 direccin IP puede ser red.local.local.local para Clase A hasta red.red.red.local
para clase C.
A partir de una direccin IP, una red puede determinar si los datos se enviarn a travs de
una compuerta (GTW, ROUTER). Obviamente, si la direccin de la red es la misma que la
direccin actual (enrutamiento a un dispositivo de red local, llamado host directo), se evitar
la compuerta ; pero todas las dems direcciones de red se enrutarn a una compuerta para
que salgan de la red local. La compuerta que reciba los datos que se transmitirn a otra red,
tendr entonces que determinar el enrutamiento can base en la direccin IP de los datos y
una tabla interna que contiene la informacin de enrutamiento.
Otra de las ventajas que ofrece el direccionamiento IP es el uso de direcciones de difusin
(broadcast addresses), que hacen referencia a todos los host de la misma red. Segn el
estndar, cualquier direccin local (hostid) compuesta toda por 1s est reservada para
difusin (broadcast). Por ejemplo, una direccin que contenga 32 1s se considera un mensaje
difundido a todas las redes y a todos los dispositivos. Es posible difundir en todas las
mquinas de una red alterando a 1s toda la direccin local o de anfitrin (hostid), de manera
que la direccin 147.10.255.255 para una red de Clase B se recibira en todos los dispositivos
de dicha red ; pero los datos no saldran de dicha red.

Direcciones de red y difusin


La mayor ventaja de la codificacin de informacin 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 anfitrin individual. En vez de
eso, una direccin IP con campo hostID a 0 se utiliza para referirse a la red en s misma.
14
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

En resumen:
Las direcciones IP se pueden utilizar para referirse a redes as como a anfitriones
individuales. Por regla, una direccin 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
direccin de difusin (BROADCAST) que se refiere a todos los anfitriones de la red. De
acuerdo con el estndar, cualquier campo hostID consistente solamente en 1s, esta
reservado para la difusin (BROADCAST). Esto permite que un sistema remoto enve
un slo paquete que ser publidifundido en la red especificada.

Resumen de reglas especiales de direccionamiento


En la prctica, el IP utiliza slo unas cuantas combinaciones de ceros ("est") o unos
("toda"). Las posibilidades son las siguientes :
TODOS 0 - ste anfitrin (permitido solamente en el arranque del sistema, pero
nunca es una direccin vlida de destino.
TODOS 0 | ANFITRIN - Anfitrin en sta RED (solo para arranque, no
como dir. vlida)
TODOS 1 - Difusin limitada (red local) (Nunca es una direccin vlida de
origen)
RED | TODOS 1 - Difusin dirigida para RED (" " )
127 | NADA (a menudo 1) - LOOPBACK (nunca debe aparecer en una red)

Como se menciona arriba, la utilizacin de todos los ceros para la red slo est permitida durante
el procedimiento de iniciacin de la maquina. Permite que una mquina se comunique
temporalmente. Una vez que la mquina "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 autnomo se les denomina "interiores" con respecto a
otro.
En redes como InterNet que tienen varias rutas fsicas, los administradores por lo general
seleccionan una de ellas como ruta primaria. Los ruteadores interiores normalmente se
comunican con otros, intercambian informacin de accesibilidad a red o informacin de
ruteo de red, a partir de la cual la accesibilidad se puede deducir.
A diferencia de esto, en la comunicacin de un router exterior no se ha desarrollado un
solo protocolo que se utilice con los sistemas autnomos.

15
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Protocolo de Informacin de Ruteo (RIP).


Uno de los I.G.P. (Interior Gateway Protocol) ms ampliamente utilizados es el RIP,
tambin conocido con el nombre de un programa que lo implementa (el routeD o Route
Daemon).
El protocolo RIP es consecuencia directa de la implantacin del ruteo de vector-distancia
para redes locales. En principio, divide las mquinas participantes en activas o pasivas
(silenciosas). Los routers activos anuncian sus rutas a los otros; las mquinas pasivas
listan y actualizan sus rutas con base a estos anuncios. Slo un router puede correr RIP
en modo activo de modo que un anfitrin deber correr el RIP en modo pasivo.
Un router con RIP en activo difunde un mensaje cada 30 segundos, ste mensaje
contiene informacin tomada de la base de datos de ruteo actualizada. Cada mensaje
consiste en pares, donde cada par contiene una direccin 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 mtrica por nmero de
saltos donde se considera que 16 saltos o ms es infinito. De esta manera, el nmero 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 nmero 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 ms 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 lmite 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 deteccin 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 mxima posible (RIP utiliza 16 saltos como medida mxima). 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 aparecern inconsistencias, debido a que los mensajes de actualizacin de
ruteo se difunden lentamente a travs de la red. Seleccionando un infinito pequeo (16)
se ayuda a limitar la convergencia lenta, pero NO se elimina.

16
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 actualizacin transportan nicamente pares de redes de destino y
distancias hacia estas redes.

Solucin al problema de la convergencia lenta:


Es posible resolver el problema de la convergencia lente mediante una tcnica conocida
como actualizacin 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 informacin acerca de la ruta de regreso sobre la misma
interfaz. Con esto evitamos que la informacin "negativa" no sea difundida con rapidez.
Una de las tcnicas finales para resolver el problema de la convergencia lenta se conoce
como Poison Reverse. Una vez que una conexin desaparece, el router anuncia la
conexin conservando la entrada de informacin por varios periodos de actualizacin e
incluye un costo infinito en la difusin. Para hacer el Poison Reverse ms efectivo, se
debe combinar con las Triggered Updates (actualizaciones activadas) que obligan al
router a que enve una difusin inmediatamente al recibir "malas noticias", en lugar de
esperar el prximo periodo de difusin. Al enviar una actualizacin inmediatamente, un
router minimiza el tiempo en que es vulnerable por recibir "buenas noticias".

Protocolo SPF abierto (OSPF).


El algoritmo de propagacin de rutas abierto (OSPF) propone los siguientes objetivos:
- Tecnologa de estado de enlaces.
- Soporta tipos de servicio (los administradores pueden instalar mltiples 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 mltiples rutas hacia un destino con el mismo costo, el OSPF
distribuye el trfico entre todas las rutas de la misma manera. Ntese que el RIP
calcula una sola ruta para cada destino).
- Particin en reas.
- Propagacin de modificaciones entre los enlaces.
- Localizacin automtica de routers vecinos.
- Propagacin de rutas aprendidas de fuentes externas.
- Routers designados en redes multiacceso.

17
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Protocolo de resolucin de direcciones


El objetivo es disear un software de bajo nivel que oculte las direcciones fsicas (MAC)
y permita que programas de un nivel ms alto trabajen slo con direcciones IP. La
transformacin 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 travs de una red fsica
hacia su destino final. La computadora que enva el paquete tiene que transformar la
direccin IP de destino final en su direccin fsica (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 direccin
IP del router en una direccin fsica.
El problema de transformar direcciones de alto nivel en direcciones fsicas se conoce
como problema de asociacin de direcciones (Address Resolution Problem). Este
problema se suele resolver, normalmente, mediante tablas en cada mquina que
contienen pares de direcciones, de alto nivel y fsicas.
En el problema de asociacin de direcciones en TCP/IP para redes con capacidad de
difusin como Ethernet, se utiliza un protocolo de bajo nivel para asignar direcciones en
forma dinmica y evitar as la utilizacin de una tabla de conversiones. Este protocolo es
conocido como Protocolo de Asociacin de Direcciones (ARP - Address Resolution
Protocol). La idea detrs de la asociacin dinmica con ARP es muy sencilla: cuando un
host A quiere definir la direccin IP (IPb), transmite por difusin (broadcast) un paquete
especial que pide al anfitrin (host) que posee la direccin IP (IPb), que responda con su
direccin fsica (Pb). Todos los anfitriones reciben la solicitud, incluyendo a B, pero slo
B reconoce su propia direccin IP y enva una respuesta que contiene su direccin fsica.
Cuando A recibe la respuesta, utiliza la direccin fsica para enviar el paquete IP
directamente a B. En resumen:

El ARP permite que un anfitrin encuentre la direccin fsica de otro


anfitrin dentro de la misma red fsica con slo proporcionar la direccin
IP de su objetivo.La informacin se guarda luego en una tabla ARP de
orgenes y destinos.

Protocolo de Asociacin de Direcciones por Rplica (RARP).


Una mquina sin disco utiliza un protocolo TCP/IP para internet llamado RARP
(Protocolo Inverso de Asociacin de Direcciones) o Reverse Address Resolution
Protocol, a fin de obtener su direccin IP desde un servidor.
En el arranque del sistema, una mquina de estas caractersticas (sin HDD permanente)
debe contactar con un servidor para encontrar su direccin IP antes de que se pueda

18
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

comunicar por medio del TCP/IP. El protocolo RARP utiliza el direccionamiento fsico
de red para obtener la direccin IP de la mquina. El mecanismo RARP proporciona la
direccin hardware fsica de la mquina de destino para identificar de manera nica el
procesador y transmite por difusin la solicitud RARP. Los servidores en la red reciben
el mensaje, buscan la transformacin en una tabla (de manera presumible en su
almacenamiento secundario) y responden al transmisor. Una vez que la mquina obtiene
su direccin 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 conexin, 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 condicin 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 informacin
sobre circunstancias inesperadas, se agreg a la familia TCP/IP un mecanismo de
mensajes de propsito especial, el Protocolo de Mensajes de Control Internet (ICMP).
El ICMP permite que los routers enven mensajes de error o de control hacia otros
routers o anfitriones, proporcionando una comunicacin entre el software de IP en una
mquina y el mismo software en otra.
Cuando un datagrama causa un error, el ICMP slo puede reportar la condicin del error
a la fuente original del datagrama; la fuente debe relacionar el error con un programa de
aplicacin individual o debe tomar alguna otra accin 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 nmeros enteros, que
identifica el mensaje; un campo CODE (CODIGO), de 8 bits, que proporciona ms
informacin sobre el tipo de mensaje, y una campo CHECKSUM (SUMA DE
VERIFICACIN), de 16 bits. Adems, los mensajes ICMP que reportan errores siempre
incluyen el encabezado y los primeros 64 bits de datos del datagrama que caus el
problema.
La razn de regresar ms que el encabezado del datagrama nicamente es para permitir
que el receptor determine de manera ms precisa qu protocolo(s) y qu programa de
aplicacin son responsables del datagrama.
El campo TYPE de ICMP define el significado del mensaje as como su formato. Los
tipos incluyen:

19
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

CAMPO TYPE Tipo de Mensaje ICMP


0 Respuesta de ECO
3 Destino inaccesible
4 Disminucin de origen (source quench -datagrama
eliminado por congestin)
5 Redireccionar (cambiar una ruta)
8 Solicitud de ECO
11 Tiempo excedido para un datagrama
12 Problema de parmetros de un datagrama
13 Solicitud de TIMESTAMP
14 Respuesta de TIMESTAMP
15 Solicitud de Informacin (obsoleto)
16 Respuesta de Informacin (obsoleto)
17 Solicitud de Mscara de direccin
18 Respuesta de mscara de direccin

Una de las herramientas de depuracin ms utilizadas incluye los mensajes ICMP de


echo request (8) y echo reply (0). En la mayora 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 mayora de los Sistemas Operativos actuales soportan multiprogramacin. Puede
parecer natural decir que un proceso es el destino final de un mensaje. Sin embargo,
especificar que un proceso en particular en una mquina en particular es el destino final
para un datagrama es un poco confuso. Primero, por que los procesos se crean y se
destruyen dinmicamente, los transmisores rara vez saben lo suficiente para identificar
un proceso en otra mquina. Segundo, nos gustara poder reemplazar los procesos que
reciben datagramas, sin tener que informar a todos los transmisores (v.q. reiniciar la
mquina 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
funcin (v.q. permitir que un transmisor contacte un servidor de ficheros sin saber qu
proceso en la mquina de destino implanta la funcin de FS).
En vez de pensar en un proceso como destino final, imaginaremos que cada mquina
contiene un grupo de puntos abstractos de destino, llamados puertos de protocolo. Cada
puerto de protocolo se identifica por medio de un nmero entero positivo.

20
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Para comunicarse con un puerto externo, un transmisor necesita saber tanto la direccin
IP de la mquina de destino como el nmero de puerto de protocolo del destino dentro de
la mquina.
El UDP proporciona el mecanismo primario que utilizan los programas de aplicacin
para enviar datagramas a otros programas de aplicacin. El UDP proporciona puertos de
protocolo utilizados para distinguir entre muchos programas que se ejecutan en la misma
mquina. Esto es, adems de los datos, cada mensaje UDP contiene tanto en nmero de
puerto de destino como el nmero de puerto origen, haciendo posible que el software
UDP en el destino entregue el mensaje al receptor correcto y que ste enve una
respuesta.
El UDP utiliza el Protocolo Internet subyacente para transportar un mensaje de una
mquina a otra y proporciona la misma semntica de entrega de datagramas, sin
conexin y no confiable que el IP. No emplea acuses de recibo para asegurarse de que
llegan mensajes, no ordena los mensajes entrantes, ni proporciona retroalimentacin para
controlar la velocidad del flujo de informacin entre las mquinas. Por tanto, los
mensajes UDP se pueden perder, duplicar o llegar sin orden. Adems, los paquetes
pueden llegar ms rpido de lo que el receptor los puede procesar. En resumen:
El UDP proporciona un servicio de entrega sin conexin y no confiable,
utilizando el IP para transportar mensajes entre mquinas. Emplea el IP
para llevar mensajes, pero agrega la capacidad para distinguir entre varios
destinos dentro de la computadora anfitrin.
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 verificacin UDP.

Figura 2. Estructura
simplificada de UDP

21
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Figura 3. Datagrama UDP/IP completo. Relacin entre el datagrama IP y el datagrama UDP

Protocolo de control de transmisin (TCP)


Servicio de Transporte de Flujo Confiable

Figura 4. Estructura bsica de un paquete TCP/IP

Figura 5. Relacin entre un datagrama IP y un segmento TCP

22
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

En las secciones anteriores hemos visto el servicio de entrega de paquetes sin conexin y no
confiable, que forma la base para toda comunicacin en InterNet, as como el protocolo IP
que lo defina.
Ahora veremos el segundo servicio ms importante y mejor conocido a nivel de red, la
entrega de flujo confiable (Reliable Stream Transport), as como el Protocolo de Control de
Transmisin (TCP) que lo define.
En el nivel ms bajo, las redes de comunicacin 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 dinmicamente los paquetes pueden
entregarlos en desorden, con retraso o duplicados. En el nivel ms alto, los programas de
aplicacin a menudo necesitan enviar grandes volmenes de datos de una computadora a
otra. Utilizar un sistema de entrega de conexin y no confiable para transferencias de
grandes volmenes de informacin resulta ser la peor opcin. Debido a esto, el TCP se ha
vuelto un protocolo de propsito general para estos casos.
La interfaz entre los programas de aplicacin y la entrega confiable (es, decir, las
caractersticas del TCP) se caracterizan por cinco funciones :
Servicio Orientado a Conexin : El servicio de entrega de flujo en la mquina
destino pasa al receptor exactamente la misma secuencia de bytes que le pasa el
transmisor en la mquina origen.
Conexin de Circuito Virtual : Durante la transferencia, el software de protocolo
en las dos mquinas contina comunicndose para verificar que los datos se reciban
correctamente. Si la comunicacin no se logra por cualquier motivo (v.q. falla el
hardware de red), ambas mquinas detectarn la falla y la reportarn a los programas
apropiados de aplicacin. Se utiliza el trmino circuito virtual para describir dichas
conexiones porque aunque los programas de aplicacin visualizan la conexin 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 aplicacin envan un
flujo de datos a travs del circuito virtual pasando repetidamente bytes de datos al
software de protocolo. Cuando se transfieren datos, cada aplicacin utiliza piezas del
tamao que encuentre adecuado, que pueden ser tan pequeas 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, ponindolos a disposicin del programa de
aplicacin 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 aplicacin. Para hacer eficiente la transferencia y
minimizar el trfico 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 aplicacin genera el flujo un byte a
la vez, la transferencia a travs de la red puede ser sumamente eficiente. De forma
similar, si el programa de aplicacin genera bloques de datos muy largos, el software

23
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

de protocolo puede dividir cada bloque en partes ms pequeas para su transmisin.


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 funcin de push slo garantiza que los datos se transferirn, por tanto, an 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 congestin).
Flujo no estructurado : Posibilidad de enviar informacin de control junto a datos.
Conexin Full Duplex : Se permite la transferencia concurrente en ambas
direcciones. Desde el punto de vista de un proceso de aplicacin, una conexin full
duplex permite la existencia de dos flujos independientes que se mueven en
direcciones opuestas, sin ninguna interaccin aparente. Esto ofrece una ventaja : el
software subyacente de protocolo puede enviar datagramas de informacin de
control de flujo al origen, llevando datos en la direccin 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 mquina a otra sin prdida o duplicacin. Surge ahora la pregunta
contradictoria: Cmo puede el software subyacente de protocolo proporcionar una
transferencia confiable si el sistema subyacente de comunicacin slo ofrece una entrega
NO confiable de paquetes ?.
La respuesta es complicada, pero la mayor parte de los protocolos confiables utilizan una
tcnica fundamental conocida como acuse de recibo positivo con retransmisin. La tcnica
requiere que un receptor se comunique con el origen y le enve un mensaje de acuse de
recibo (ACK) conforme recibe los datos (ver los primeros temas para una descripcin ms
detallada). El transmisor guarda un registro de cada paquete que enva y espera un ACK
antes de enviar el siguiente paquete. El transmisor tambin arranca un temporizador cuando
enva 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 tambin pueden surgir cuando las redes tienen grandes
retrasos que provocan la retransmisin prematura. Para evitar la confusin causada por
ACKs retrasados o duplicados, los protocolos de acuses de recibo positivos envan los
nmeros 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

24
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

el envo de un nuevo paquete hasta que reciba un ACK del paquete anterior.
La solucin est en otra tcnica conocida como ventana deslizante, que es una forma ms
compleja de acuse de recibo positivo y retransmisin. Los protocolos de ventana deslizante
utilizan el ancho de banda de red de mejor forma al permitir que el transmisor enve varios
paquetes sin esperar el ACK (remitirse a captulos anteriores para una descripcin de ste
mtodo).

Puertos, conexiones y puntos extremos.


Al igual que el UDP, el TCP reside sobre el IP en el esquema de estratificacin por capas de
protocolos. El TCP permite que varios programas de aplicacin en una mquina se
comuniquen de manera concurrente y realiza el demultiplexado del trfico TCP entrante
entre los programas de aplicacin. As mismo, al igual que el UDP, el TCP utiliza nmeros
de puerto de protocolo para identificar el destino final dentro de una mquina. Cada puerto
tiene asignado un nmero entero pequeo 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 ms complejos, ya que un nmero de puerto no corresponde a
un slo objeto. El TCP utiliza la conexin, no el puerto de protocolo, como su abstraccin
fundamental ; las conexiones se identifican por medio de un par de puntos extremos.
Un punto extremo es un par de nmeros enteros (host, puerto), en donde host es la direccin
IP de un anfitrin y puerto es el un puerto TCP en dicho anfitrin.
Las conexiones vienen definidas por dos puntos extremos, y es ms : la abstraccin de la
conexin 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 conexin por medio de un par de puntos extremos, y por eso varias conexiones en la
misma mquina pueden compartir un nmero de puerto TCP.
El TCP combina la asignacin dinmica y esttica de puertos mediante un conjunto de
asignacin de puertos bien conocidos para programas llamados con frecuencia, pero la
salida de la mayor parte de los nmeros disponibles para el sistema se asigna conforme los
programas lo necesitan.
La siguiente tabla muestra un ejemplo de nmeros de puerto TCP asignados actualmente.

Puerto/protocolo Descripcin

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

25
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 Da)

19/tcp Protocolo Chargen Generador de caractres

19/udp Protocolo Chargen Generador de caractres

FTP File Transfer Protocol (Protocolo de Transferencia de Ficheros)


20/tcp
datos

FTP File Transfer Protocol (Protocolo de Transferencia de Ficheros)


21/tcp
control

22/tcp SSH, scp, SFTP

23/tcp Telnet comunicaciones de texto inseguras

SMTP Simple Mail Transfer Protocol (Protocolo Simple de Transferencia


25/tcp
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), tambin usado por DHCP

68/udp BOOTP BootStrap Protocol (Client), tambin usado por DHCP

TFTP Trivial File Transfer Protocol (Protocolo Trivial de Transferencia


69/udp
de Ficheros)

70/tcp Gopher

79/tcp Finger

HTTP HyperText Transfer Protocol (Protocolo de Transferencia de


80/tcp
HiperTexto) (WWW)

26
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

88/tcp Kerberos Agente de autenticacin

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

111/tcp sunrpc

113/tcp ident (auth) antiguo sistema de identificacin

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

123/udp NTP Protocolo de sincronizacin de tiempo

123/tcp NTP Protocolo de sincronizacin de tiempo

135/tcp epmap

137/tcp NetBIOS Servicio de nombres

137/udp NetBIOS Servicio de nombres

138/tcp NetBIOS Servicio de envo de datagramas

138/udp NetBIOS Servicio de envo 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 gestin de displays en X11

177/udp XDMCP Protocolo de gestin 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 pginas web

Microsoft-DS (Active Directory, comparticin en Windows, gusano


445/tcp
Sasser, Agobot)

445/udp Microsoft-DS comparticin de ficheros

500/udp IPSec ISAKMP, Autoridad de Seguridad Local

27
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 impresin de Unix

666/tcp identificacin 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 mquinas 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

28
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 gestin de bases de datos

3389/tcp RDP (Remote Desktop Protocol)

3396/tcp Novell agente de impresin NDPS

3690/tcp Subversion (sistema de control de versiones)

4662/tcp eMule (aplicacin de comparticin de ficheros)

4672/udp eMule (aplicacin de comparticin de ficheros)

RAdmin (Remote Administrator), herramienta de administracin remota


4899/tcp
(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 conexin de cliente

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

5269/tcp XMPP/Jabber conexin de servidor

5432/tcp PostgreSQL sistema de gestin 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 (conexin normal)

29
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

6000/tcp X11 usado para X-windows

6112/udp Blizzard

6129/tcp Dameware Software conexin remota

6346/tcp Gnutella comparticin 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

iRDMI por lo general, usado errneamente en sustitucin de 8080.


8000/tcp
Tambin 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 (Administracin remota web)

19226/tcp Panda SecurityPuerto de comunicaciones de Panda Agent.

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

Back Orifice herramienta de administracin remota (por lo general


31337/tcp
troyanos)

30
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

LA INTERFACE SOCKET

31
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Introduccin
Los sockets son interfaces lgicos de entrada/salida que permiten la comunicacin entre
procesos que pueden residir en mquinas distintas pero que estn conectadas mediante
una red. Es el mecanismo utilizado por las aplicaciones en red basadas en tecnologa
Internet, de ah su importancia dada la difusin 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 gestin de un determinado
recurso de una mquina. El cliente, que, en general, se ejecuta en una mquina diferente,
interacciona con el recurso remoto estableciendo una comunicacin con el servidor,
siguiendo las reglas impuestas por el protocolo de nivel de aplicacin que corresponda.
Tras esta introduccin a las comunicaciones en redes tipo Internet, pasamos a describir
los interfaces de programacin que permiten el acceso a los sockets en distintos
lenguajes y sistemas operativos.

SOCKETS
Los sockets son interfaces lgicos que permiten la comunicacin bidireccional entre
procesos que se ejecutan en una misma mquina o en mquinas distintas conectadas en
red. Por ejemplo, los navegadores web se comunican con los servidores web mediante
sockets. Es frecuente encontrar en la bibliografa analogas entre sockets y telfonos o
buzones de correo. En cierto modo, estos ltimos permiten la comunicacin entre
personas de forma similar a como los sockets hacen posible la interaccin entre procesos.
La comunicacin mediante sockets es el mecanismo usado por la aplicaciones en red que
se basan en tecnologa Internet, es decir, en la familia de protocolos TCP/IP. De hecho,
un socket no es ms que la implementacin 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 mquina) para comunicarse con el socket
remoto dispuesto por el servidor web. Por extensin, suele hablarse tambin de proceso
local/remoto o incluso de mquina local/remota.

Identificacin de un socket
Desde el punto de vista de un proceso, un socket no es ms 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 continuacin.

32
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 vacos los niveles de sesin y presentacin.
Sobre una capa dependiente de la tecnologa de red usada, encontramos el protocolo de
nivel de red IP (Internet Protocol), responsable bsicamente del direccionamiento de las
estaciones y del enrutamiento de paquetes. Para nuestros propsitos, lo importante aqu
es que, en la red, una mquina se distingue unvocamente de las dems mediante su
direccin de nivel de red, llamada direccin 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 ms 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 mquina. Es decir, un socket que reside en una cierta mquina se distingue
unvocamente de los dems sockets de la misma mquina mediante su direccin 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 mquina. Como consecuencia de todo lo anterior, un socket se identifica
indicando la mquina en la que reside y el puerto al que est asociado, es decir:
socket: (direccin IP, puerto)
Las direcciones IP estn 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
direccin 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

33
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

ejemplo, la direccin 127.0.0.1, cuya utilidad se explica a continuacin. Toda mquina


con capacidad de comunicaciones TCP/IP responde, al menos, a la direccin 127.0.0.1,
aunque ni siquiera est conectada a la red. Esto nos permite establecer comunicacin
entre procesos locales mediante sockets sin necesidad de que el equipo posea una
direccin IP real (o bien, aunque la posea, no necesitamos conocerla para establecer
comunicaciones locales). La direccin 127.0.0.1 nos permite comprobar el buen
funcionamiento de la pila de protocolos.
Dado que la identificacin de los equipos por su direccin IP es poco amigable, se
desarroll el servicio de nombres de dominio (DNS, Domain Name Service) que asocia
la direccin IP de un host con un nombre de la forma host.dominio. Gracias a este
sistema, podemos especificar en nuestro navegador la direccin 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.
Anlogamente, la direccin 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 estn asignados para las aplicaciones estndar de Internet1. Por ejemplo, el
puerto 80 es el puerto estndar 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 travs del socket identificado por (dir.
IP = 150.214.180.50, Puerto = 80).

Tipos de sockets
Como hemos visto, los sockets estn 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 conexin.
La comunicacin entre sockets TCP es fiable (sin prdida de paquetes), ordenada
(TCP nos proporciona los paquetes en la secuencia correcta) y sin duplicacin de
paquetes. TCP, y consecuentemente, este tipo de sockets, es orientado a la conexin.
Esto quiere decir que los sockets de los extremos a comunicar deben establecer un
circuito virtual a travs del cual se producir el intercambio de informacin. El
establecimiento del circuito virtual se suele denominar conexin, y es el paso previo al
intercambio de datos. Una vez finalizado ste, se procede

1
Esta asignacin 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 estndares, borradores
de estndar y recomendaciones sobre todos los aspectos de Internet.
2
A veces es posible usar, adems de los tipos de sockets descritos, un tipo especial denominado "raw", a
travs del cual se tiene acceso directamente al protocolo IP, dejando vaco el nivel de transporte.

34
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

la desconexin. En la analoga que sealbamos al principio del apartado 2, los


sockets TCP se parecen ms a los telfonos, en los cuales la conexin se corresponde
con la realizacin de una llamada. El destino es seleccionado gracias a su nmero de
telefno y avisado mediante los tonos apropiados. Cuando el destino descuelga, se
establece el circuito virtual y es posible la comunicacin bidireccional. Cuando sta
termina, los dos extremos cuelgan, cerrando el circuito.

Sockets UDP, datagram o no orientados a la conexin.


La comunicacin entre sockets UDP no garantiza la llegada de todos los paquetes, ni
su orden, ni su unicidad. La aplicacin que use sockets de este tipo tendr que
encargarse de resolver estos problemas potenciales. Para la comunicacin 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 analoga
anterior, los sockets UDP se parecen ms a los buzones de correo. El emisor slo se
encarga de introducir la informacin en el buzn. El servicio de correos, que
representa a la red de comunicaciones, transporta la informacin hasta el destino,
introducindola en su buzn. En ningn 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 informacin se pierde; en la comunicacin entre sockets UDP
no hay el equivalente postal a la devolucin al remitente).
A partir de este punto, nos ocuparemos nicamente de los sockets TCP.

Modelo de comunicacin 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 algn tipo de recurso,
por ejemplo, pginas web o una base de datos. El servidor es, por tanto, un
proceso ininterrumpido, ya que sin l, el recurso no estara 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 tambin rol de cliente desde el punto de
vista de un tercer proceso.

35
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Proceso de conexin cliente-servidor


El proceso de conexin entre cliente y servidor se ha representado en la figura 2, y se
describe a continuacin.
1- El proceso servidor, en su arranque, reserva un socket, s, denominado socket
servidor, en su mquina local, y se queda en estado de espera, figura 2a.
2- El socket servidor (direccin IP y nmero 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 enva una solicitud de conexin al
socket servidor, figura 2b.
3- El proceso servidor, que recibe la solicitud del cliente a travs del socket
servidor, crea un nuevo socket, s, que se encargar de la comunicacin con el
cliente que ha solicitado la conexin, y lo conecta al socket cliente, figura 2c. El
nuevo socket hereda la direccin del socket servidor (direccin 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 tambin un nuevo proceso servidor, que se encargar de
atender las solicitudes de dicho cliente.
Una vez establecida la comunicacin, es posible el intercambio de informacin.
Dado que son sockets de tipo TCP, se tiene garanta de que todos los datos llegarn,
y adems, en el orden correcto, y sin duplicados.
4- Cuando el intercambio de informacin termina, el proceso cliente y el proceso
que atiende a ste en el servidor cierran sus respectivos sockets, finalizando as la
conexin. Por tanto, volvemos al estado inicial, figura 2.

3
El socket que se ha creado en la mquina servidora para llevar a cabo la comunicacin con el cliente
tiene caractersticas similares al socket cliente, esto es, no est en estado de escucha, sino preparado para
enviar y recibir informacin.
4
Esto es, que tienen varios procesos ejecutndose concurrentemente en la mquina.

36
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

37
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Modelo de programacin
El proceso de conexin 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.

38
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Las acciones que aparecen en el diagrama se explican a continuacin. El proceso


servidor crea (abre) el socket servidor(socket), le asigna un puerto (bind) en la
mquina servidora y lo prepara para la escucha (listen), asignndole una cola de
conexiones pendientes de procesar. A partir de este momento, el socket pasa a estado de
espera de conexin 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 comunicacin.
Cuando el proceso servidor recibe tal solicitud, ste crea un proceso hijo para que se
encargue de la comunicacin con el cliente. Tambin crea un socket (accept) y se lo
asigna al nuevo proceso. El proceso servidor vuelve a su estado de espera de conexin
(accept).
El proceso cliente y el proceso hijo del servidor intercambian informacin (send, recv).
Normalmente, aunque no es obligatoriamente as, el cliente es el primero que enva
informacin (tal como aparece en la figura 3). Cuando la comunicacin 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 estndar POSIX. Windows
tambin 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 (segn el estndar POSIX) para la manipulacin de sockets; dada la semejanza
con su equivalente en Windows, el apartado 4.2 se limita a mostrar las diferencias entre
ellos. ste incluye tambin una breve referencia acerca de las clases disponibles para la
programacin de sockets bajo C++ usando las MFC (Microsoft Foundation Classes). Por
ltimo, el apartado 4.3 hace una breve introduccin a la programacin 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 recompilacin.

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, convencin little endian) y Motorola 680xx (primero el byte ms
significativo, convencin big endian).
Para solucionar el problema, se distinguen dos tipos de ordenamiento: el host order (el

39
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 convencin para las redes tipo
Internet, concretamente big endian), y se establecen las siguientes reglas:
todos los datos que se enven 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 cules sean los host order de A y B, la
comunicacin 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 envo es relevante slo cuando la unidad de
informacin tiene una longitud superior a un byte.
Las funciones short htons(short) y long htonl(long) realizan la conversin 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 estn definidas en el fichero de cabecera
<netinet/in.h>.

Programacin de sockets en Windows


Bajo Windows, las operaciones de sockets son competencia de la librera dinmica
winsock2 (Windows Sockets Version 2). Bsicamente, 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 convencin, estn
precedidas por el prefijo WSA-. Tan slo trataremos con las ms fundamentales de estas
funciones aadidas tipo WSA-. A continuacin se enumeran los aspectos propios de
Windows en cuanto a la programacin 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 aadir al enlazador (linker) la librera esttica ws2_32.lib. En
Microsoft Visual C++ 6.0, esto se hace incluyndola 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 funcin listen() pasa a ser int
listen(SOCKET s, int backlog); anlogamente 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).

40
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

El resto de funciones que manejan sockets (que devuelven int) indican una
situacin de error mediante la constante SOCKET_ERROR (en lugar de devolver
-1). Es el caso, por ejemplo, de send() y recv().
La funcin 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 cdigo de error.
Antes de realizar cualquier llamada a winsock2 es necesario invocar la funcin
WSAStartup(), que se encarga de iniciar esta librera. Anlogamente, cuando ya
no sea necesario seguir usando winsock2, debe llamarse a WSACleanup().
Tpicamente, el cdigo 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 ms informacin sobre la programacin de sockets en Windows, puede consultarse
la MSDN Library Visual Studio, en Platform SDK > Networking and Distributed
Services > Windows Sockets Version 2 API.

Programacin de sockets en Windows usando C++ y MFC


Microsoft ha desarrollado un conjunto de clases C++ que encapsulan prcticamente 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 aplicacin con un enfoque
orientado a objetos para Windows. En MFC, se definen dos clases relacionadas con
sockets:

41
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

CAsyncSocket. Encapsula las funciones descritas en el apartado anterior,


facilitando adems la posibilidad de realizar programacin orientada a eventos,
de forma que se pueden definir funciones de callback que son notificadas cuando
se ha recibido informacin, cuando el socket est libre para seguir enviando, etc.
CSocket. Deriva de la anterior. Proporciona un interfaz con un mayor nivel de
abstraccin, evitando detalles que s aparecen en CAsyncSocket. En particular,
las funciones de Csocket incorporan bloqueo.
Para ms informacin, consultar la MSDN Library Visual Studio.

42
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Fundamentos sobre el control


MSWinsockControl

43
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

El MSWinsockControl incluido con Visual C++ es una herramienta muy poderosa para
la creacin 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 (pginas Web) puerto 80
FTP File Transfer Protocol (transferencia de ficheros) puerto 21
SMTP Simple Mail Transfer Protocol (envo de email) puerto 25
POP3 Post Office Protocol (recepcin 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 ms 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 transmisin
(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
ejecucin.

Aplicaciones posibles
- Crear una aplicacin cliente que recopile informacin del usuario antes de
enviarla a un servidor central.
- Crear una aplicacin servidora que funcione como un punto central de
recopilacin de datos procedentes de varios usuarios.
- Crear una aplicacin de "conversacin".

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 conexin:
TCP es un protocolo basado en la conexin y es anlogo a un telfono: el usuario
debe establecer una conexin antes de continuar.
UDP es un protocolo sin conexin y la transaccin entre los dos equipos es como

44
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

pasar una nota: se enva un mensaje desde un equipo a otro, pero no existe una
conexin explcita entre ambos. Adems, el tamao mximo de los datos en
envos individuales est determinado por la red.
La naturaleza de la aplicacin 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 aplicacin la confirmacin por parte del cliente o el servidor
cuando se enven o reciban datos? Si es as, el protocolo TCP requiere
una conexin explcita antes de enviar o recibir datos.
2- Ser muy grande el tamao de los datos (como en el caso de los archivos
de imgenes o sonidos)? Una vez establecida la conexin, el protocolo
TCP mantiene la conexin y asegura la integridad de los datos. No
obstante, esta conexin utiliza ms recursos del sistema, por lo que
resulta ms "cara".
3- Se envian los datos de forma intermitente o en una sesin? Por ejemplo,
si se est creando una aplicacin que avisa a equipos especficos cuando
se han completado ciertas tareas, el protocolo UDP puede ser el ms
apropiado. Este protocolo es tambin el ms adecuado para enviar
pequeas cantidades de datos.

Establecer el protocolo
Para establecer el protocolo que la aplicacin va a usar: en tiempo de diseo, en la
ventana Propiedades, Se entra en Protocolo y se selecciona sckTCPProtocol o
sckUDPProtocol. Tambin se puede establecer la propiedad Protocol en el cdigo, como
se muestra a continuacin:
Cdigo:
Winsock1.Protocol = sckTCPProtocol

Determinar el nombre del equipo


Para conectarse a un equipo remoto, se deber saber su direccin IP o su "nombre
descriptivo". La direccin IP est formada por un conjunto de tres dgitos separados por
puntos (xxx.xxx.xxx.xxx). En general, es mucho ms fcil 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 Configuracin, se hace clic en Panel de control.
3- Se hace doble clic en el icono Red.
4- Se hace en la ficha Identificacin.

45
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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


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

Conceptos bsicos de conexin con el protocolo TCP


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

Aceptar ms de una solicitud de conexin


Un servidor bsico slo acepta una solicitud de conexin. No obstante, es posible aceptar
varias solicitudes de conexin con el mismo control si crea una matriz de controles. En
este caso, no necesita cerrar la conexin; basta con crear una nueva instancia del control
(estableciendo la propiedad Index) e invocar el mtodo Accept de la nueva instancia.

Conceptos bsicos del protocolo UDP


Crear una aplicacin UDP es todava ms sencillo que crear una aplicacin TCP, ya que
el protocolo UDP no requiere una conexin explcita. En la aplicacin TCP anterior hubo
que establecer explcitamente un control Winsock para "escuchar", mientras que el otro
deba iniciar la conexin con el mtodo Connect.

En cambio, el protocolo UDP no requiere una conexin explcita. Para enviar datos entre
los dos controles, se deben completar tres pasos (en ambos lados de la conexin):

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 mtodo Bind especificando la propiedad LocalPort que se va a usar.
(Este mtodo se trata detenidamente ms adelante.)

Acerca del mtodo Bind


Este mtodo "reserva" un puerto local para uso del control. Por ejemplo, al enlazar el
control al nmero de puerto 1001, ninguna otra aplicacin podr usar ese puerto para
"escuchar". Esto puede ser muy til si desea impedir que otra aplicacin utilice ese
puerto.

46
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

El mtodo Bind tambin ofrece un segundo argumento opcional. Si hay ms 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 dilogo Red de la opcin Configuracin 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 conexin 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 mtodos del control, podr
conectar fcilmente con un equipo remoto e intercambiar datos en las dos direcciones.

Conceptos bsicos de TCP


El Protocolo de control de transferencia (TCP) permite crear y mantener una conexin
con un equipo remoto. Mediante la conexin, ambos equipos pueden intercambiar datos
entre s.
Si se est creando una aplicacin de cliente, se debe saber el nombre del equipo servidor
o su direccin IP (propiedad RemoteHost), as como el puerto (propiedad RemotePort)
en el que se est "escuchando". Despus, llamar al mtodo Connect.
Si se est creando una aplicacin de servidor, se debe establecer el puerto (propiedad
LocalPort) en el que escuchar y llamar al mtodo Listen. Cuando el equipo cliente
solicite una conexin, se producir el evento ConnectionRequest. Para completar la
conexin, llamar al mtodo Accept del evento ConnectionRequest.
Una vez establecida la conexin, los equipos pueden enviar y recibir datos. Para enviar
datos, se debe llamar al mtodo SendData. Siempre que se reciben datos, se produce el
evento DataArrival. Llamar al mtodo GetData del evento DataArrival para recuperar los
datos.

Conceptos bsicos 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 conexin.
Asimismo, una aplicacin UDP puede ser cliente o servidor.
Para transmitir datos, establecer primero la propiedad LocalPort del equipo cliente. El

47
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

equipo servidor slo necesita establecer RemoteHost a la direccin de Internet del equipo
cliente y la propiedad RemotePort al mismo puerto que la propiedad LocalPort del
equipo cliente, y llamar al mtodo SendData para comenzar a enviar mensajes. Despus,
el equipo cliente utiliza el mtodo GetData del evento DataArrival para recuperar los
mensajes enviados.

Propiedades Winsock(control)

BytesReceived (Propiedad)
Devuelve la cantidad de datos recibidos (que estn actualmente en el bfer de recepcin).
Utilice el mtodo GetData para recuperar los datos.
Es de slo lectura y no est disponible en tiempo de diseo.
- Sintaxis: objeto.BytesReceived
- Valor devuelto: Long

LocalHostName (Propiedad)
Devuelve el nombre de la mquina local. Es de slo lectura y no est disponible en
tiempo de diseo.
- Sintaxis: objeto.LocalHostName
- Valor devuelto:String

LocalIP (Propiedad)
Devuelve la direccin IP de la mquina local en el formato de cadena con puntos de
direccin IP (xxx.xxx.xxx.xxx). Es de slo lectura y no est disponible en tiempo de
diseo.
- 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 diseo.
En el cliente, designa el puerto local desde el que desea enviar los datos.
Especifique el puerto 0 si la aplicacin no necesita un puerto especfico. En este
caso, el control seleccionar un puerto de forma aleatoria. Una vez establecida la
conexin, ste es el puerto local utilizado para la conexin TCP.
En el servidor, es el puerto local en el que se escuchar. Si especifica el puerto 0,

48
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

se utiliza un puerto seleccionado de forma aleatoria. Despus de llamar al mtodo


Listen, la propiedad contiene el puerto actual seleccionado.
- Sintaxis: objeto.LocalPort = largo
- Tipo de datos: Long

Comentarios
Para establecer dinmicamente 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 nmero de puerto (aleatorio), que pueda
proporcionar al equipo remoto para ese propsito.

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:
Cdigo:
Constante Valor Descripcin
sckTCPProtocol 0 Predeterminado. Protocolo TCP.
sckUDPProtocol 1 Protocolo UDP.

- Valor devuelto: Ninguno


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

RemoteHostIP (Propiedad)
Devuelve la direccin IP del equipo remoto.
En las aplicaciones de cliente, despus de establecer la conexin con el mtodo
Connect, esta propiedad contiene la cadena IP del equipo remoto.
En las aplicaciones de servidor, despus de la llegada de una solicitud de llamada
(evento ConnectionRequest), esta propiedad contiene la cadena IP del equipo
remoto que inici la conexin.
Cuando utiliza el protocolo UDP, despus de producirse el evento DataArrival, esta
propiedad contiene la direccin IP del equipo que enva los datos UDP.

- Sintaxis: objeto.RemoteHostIP
- Tipo de datos: String

49
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

SocketHandle (Propiedad)
Devuelve un valor que corresponde al controlador de socket que utiliza el control para
comunicarse con la capa Winsock. Es de slo lectura y no est disponible en tiempo de
diseo.
- 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 slo lectura y
no est disponible en tiempo de diseo.
- Sintaxis: objeto.State
- Tipo de datos: Integer
- Valores. Los valores de la propiedad State son:
Cdigo:
Constante Valor Descripcin
sckClosed 0 Predeterminado. Cerrado
sckOpen 1 Abierto
sckListening 2 Escuchando
sckConnectionPending 3 Conexin pendiente
sckResolvingHost 4 Resolviendo host
sckHostResolved 5 Host resuelto
sckConnecting 6 Conectando
sckConnected 7 Conectado
sckClosing 8 El equipo est cerrando la conexin
sckError 9 Error

Index (Propiedad, controles ActiveX)


Establece o devuelve el nmero que identifica inequvocamente un objeto de una
coleccin.
- Sintaxis: objeto.Index
Comentarios
La propiedad Index se establece de forma predeterminada al orden de creacin de los
objetos en una coleccin. El ndice para el primer objeto de una coleccin ser siempre
uno (1).
El valor de la propiedad Index de un objeto puede cambiar cuando se ordenan de nuevo
los objetos de la coleccin, como cuando establece la propiedad Sorted a True. Si espera
que la propiedad Index cambie dinmicamente, puede que sea ms til hacer referencia a
los objetos de una coleccin mediante la propiedad Key.

50
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Name (Propiedad)
Devuelve el nombre utilizado en el cdigo para identificar un formulario, un
control o un objeto de acceso a datos. Es de slo lectura en tiempo de ejecucin.
Devuelve o establece el nombre de un objeto fuente.
- Sintaxis: objeto.Name

Object (Propiedad, controles ActiveX)


Devuelve el objeto y un valor de un mtodo o propiedad de un objeto.
- Sintaxis: objeto.Object[.propiedad | .mtodo]
La sintaxis de la propiedad Object consta de las siguientes partes:
Cdigo:
Parte Descripcin

objeto Una expresin de objeto que da como resultado un objeto de la lista Se aplica a.
propiedad Propiedad compatible con el objeto.
mtodo Mtodo compatible con el objeto.

Comentarios
Utilizar esta propiedad para especificar un objeto que desea usar en una tarea de
Automatizacin.
Para usar en una tarea de Automatizacin el objeto devuelto por la propiedad Object,
utilizar las propiedades y los mtodos de dicho objeto. Para obtener informacin acerca
de las propiedades y los mtodos compatibles con un objeto, ver la documentacin de la
aplicacin que cre el objeto.

Parent (Propiedad)
Devuelve el formulario, objeto o coleccin que contiene un control u otro objeto o
coleccin.
- Sintaxis: objeto.Parent
Comentarios
Utilizar la propiedad Parent para tener acceso a las propiedades, los mtodos o los
controles del primario de un objeto.
La propiedad Parent es til en una aplicacin en la que se pasan objetos como
argumentos. Por ejemplo, se podra pasar una variable de control a un procedimiento
general en un mdulo y usar la propiedad Parent para tener acceso a su formulario
primario.

RemoteHost (Propiedad, controles ActiveX)

51
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Devuelve o establece el equipo remoto al que un control enva datos, o aqul del que los
recibe. Puede indicar el nombre de host, como "FTP://ftp.microsoft.com" o como una
cadena de direccin 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:
Cdigo:
Parte Descripcin
objeto Una expresin de objeto que da como resultado un objeto de la lista Se aplica a.
cadena El nombre o la direccin del equipo remoto.

Comentarios
Cuando se especifica esta propiedad, la propiedad URL se actualiza para mostrar el
nuevo valor. Adems, si se actualiza la parte de host de la direccin URL, esta propiedad
tambin se modifica para reflejar el nuevo valor.
La propiedad RemoteHost tambin puede modificarse al invocar los mtodos OpenURL
o Execute. En tiempo de ejecucin, el cambio de este valor no tiene ningn efecto hasta
la conexin siguiente.
RemotePort (Propiedad, controles ActiveX)
Devuelve o establece el nmero del puerto remoto con el que conectar.
- Sintaxis: objeto.RemotePort = puerto
La sintaxis de la propiedad RemotePort consta de la siguientes partes:
Cdigo:
Parte Descripcin
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
automticamente el puerto predeterminado correspondiente a cada protocolo. Los
nmeros de puerto predeterminados se muestran en la siguiente tabla:
Cdigo:
Puerto Descripcin
80 HTTP, utilizado habitualmente para las conexiones con el World Wide Web.
21 FTP.

Tag (Propiedad, controles ActiveX)

52
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Devuelve o establece una expresin que almacena cualquier dato adicional necesario
para su programa.
- Sintaxis: objeto.Tag [= expresin]
La sintaxis de la propiedad Tag consta de las siguientes partes:
Cdigo:
Parte Descripcin
objeto Casi cualquier objeto
expresin Cualquier texto

Winsock(Metodos)
Accept (Mtodo)
Slo para las aplicaciones de servidor TCP. Este mtodo se utiliza para aceptar una
conexin entrante cuando se est tratando un evento ConnectionRequest.
- Sintaxis: objeto.Accept IdSolicitud
- Tipo de datos: Long
- Valor devuelto: Ninguno
Comentarios
El mtodo Accept se utiliza en el evento ConnectionRequest. El evento
ConnectionRequest tiene un argumento, el parmetro RequestID, que debe pasarse al
mtodo Accept.
Debe usar el mtodo Accept en una nueva instancia del control (distinta de la que est en
estado de escucha.)

Bind (Mtodo)
Especifica el puerto local y la direccin IP local a usar en las conexiones TCP. Utilice
este mtodo si tiene mltiples adaptadores de protocolo.
- Sintaxis: objeto.Bind puertoLocal, IPLocal
La sintaxis del mtodo Bind consta de las siguientes partes:
Cdigo:
Parte Descripcin
objeto Control Winsock
puertoLocal Puerto utilizado para realizar una conexin.
IPLocal Direccin local de Internet utilizada para realizar una conexin.

Comentarios
Debe llamar al mtodo Bind antes de llamar al mtodo Listen.

Close (Mtodo, control Winsock)


53
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Cierra una conexin TCP o un socket en escucha para las aplicaciones de cliente y de
servidor.
- Sintaxis: objeto.Close
- Argumentos: Ninguno
- Valor devuelto: Ninguno

GetData (Mtodo, 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,] [longMx]
La sintaxis del mtodo GetData consta de las siguientes partes:
Cdigo:
Parte Descripcin
objeto Control Winsock
datos Dnde se almacenarn los datos recuperados despus de que el mtodo termine
correctamente. Si no hay suficientes datos disponibles para el tipo requerido, datos
se establecer a Vaco.
tipo Opcional. Tipo de datos a recuperar, como se muestra en Valores.
longMx Opcional. Especifica el tamao deseado cuando se recibe una matriz de bytes o
una cadena. Si se omite este parmetro para las matrices de bytes o las cadenas, se
recuperarn todos los datos disponibles. Si se proporciona para tipos de datos que
no sean matrices de bytes o cadenas, se pasa por alto el parmetro.

Valores
Los valores de tipo son:
Cdigo:
Descripcin 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

54
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

El mtodo GetData se suele usar con el evento DataArrival, que incluye el argumento
bytesTotales. Si especifica una longMx menor que el argumento bytesTotales, obtendr
el mensaje de advertencia 10040, que indica que se perdern los bytes restantes.

Listen (Mtodo)
Crea un socket y lo establece a modo de escucha. Este mtodo slo funciona en las
conexiones TCP.
- Sintaxis: objeto.Listen
- Argumentos: Ninguno
- Valor devuelto: Ninguno
Comentarios
El evento ConnectionRequest se produce cuando hay una conexin entrante. Cuando se
est tratando un evento ConnectionRequest, la aplicacin debera usar el mtodo Accept
(en una nueva instancia del control) para aceptar la conexin.

PeekData (Mtodo)
Similar a GetData, excepto que PeekData no elimina los datos de la cola de entrada. Este
mtodo slo funciona en las conexiones TCP.
- Sintaxis: objeto.PeekData datos, [tipo,] [longMx]
La sintaxis del mtodo PeekData consta de las siguientes partes:
Cdigo:
Parte Descripcin
objeto Control Winsock
datos Almacena los datos recuperados despus de que el mtodo acaba
satisfactoriamente. Si no hay suficientes datos disponibles para el tipo solicitado,
datos se establecer a Vaco.
tipo Opcional. Tipo de los datos a recuperar, como se describe en Valores. Valor
predeterminado: vbArray + vbByte.
longMx Opcional. Longitud que especifica el tamao 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:
Cdigo:

55
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 (Mtodo)
Enva datos a un equipo remoto.
- Valor devuelto: Ninguno
- Sintaxis: objeto.SendData datos
La sintaxis del mtodo SendData consta de las siguientes partes:
Cdigo:
Parte Descripcin
objeto Control Winsock
datos Datos que desea enviar. Para los datos binarios, debera 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 conexin. Las aplicaciones deben usar el
mtodo Close para cerrar correctamente una conexin TCP.

- Sintaxis: objeto_Close( )
- Argumentos: Ninguno

56
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Connect (Evento, control Winsock)


Ocurre cuando se ha completado una operacin de conexin.
- Sintaxis: objeto.Connect()
Comentarios
Usar el evento Connect para confirmar que se ha realizado con xito la conexin

ConnectionRequest (Evento)
Se produce cuando el equipo remoto solicita una conexin.
Slo para aplicaciones de servidor TCP. El evento se activa cuando llega una
solicitud de conexin. Las propiedades RemoteHostIP y RemotePort almacenan
la informacin acerca del cliente despus de que se ha activado el evento.
- Sintaxis: objeto_ConnectionRequest (IdSolicitud As Long)
La sintaxis del evento ConnectionRequest consta de las siguientes partes:
Cdigo:
Parte Descripcin
objeto Control Winsock
IdSolicitud Identificador de la solicitud de conexin entrante. Este argumento se debera
pasar al mtodo Accept de la segunda instancia del control.

Comentarios
El servidor puede decidir si acepta o no la conexin. Si no se acepta la conexin entrante,
el equipo (cliente) obtendr el evento Close. Utilice el mtodo Accept (en una nueva
instancia del control) para aceptar una conexin 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:
Cdigo:
Parte Descripcin
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.
Slo se activa cuando hay datos nuevos. Utilice la propiedad BytesReceived para
comprobar la cantidad de datos disponibles en cualquier momento.

57
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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(nmero As Integer, descripcin 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:
Cdigo:
Parte Descripcin
objeto Control Winsock
nmero Entero que define el cdigo de error. Vea las constantes ms abajo, en Valores.
descripcin Cadena que contiene la informacin 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 nmero son:
Cdigo:
Constante Valor Descripcin
sckOutOfMemory 7 Sin memoria
sckInvalidPropertyValue 380 El valor de la propiedad no es vlido.
sckGetNotSupported 394 No se puede leer la propiedad.
sckSetNotSupported 383 La propiedad es de slo lectura.
sckBadState 40006 Protocolo o estado de conexin incorrecto para la solicitud
o la transaccin requerida.
sckInvalidArg 40014 El argumento que se pas a una funcin no estaba en el
formato correcto o en el intervalo especificado.
sckSuccess 40017 Correcto.
sckUnsupported 40018 Tipo Variant no aceptado.
sckInvalidOp 40020 La operacin no es vlida en el estado actual.
sckOutOfRange 40021 El argumento est fuera del intervalo.
sckWrongProtocol 40026 Protocolo errneo para la solicitud o la transaccin
requerida.
sckOpCanceled 10004 Se cancel la operacin.
sckInvalidArgument 10014 La direccin solicitada es una direccin de multidifusin,
pero el indicador no est activado.
sckWouldBlock 10035 El socket es no bloqueante y la operacin especificada se

58
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

bloquear.
sckInProgress 10036 Se est efectuando una operacin de Winsock bloqueante.
sckAlreadyComplete 10037 Se complet la operacin. No se estn efectuando
operaciones bloqueantes.
sckNotSocket 10038 El descriptor no es un socket.
sckMsgTooBig 10040 El datagrama es demasiado grande para el bfer y se
truncar.
sckPortNotSupported 10043 El puerto especificado no es compatible.
sckAddressInUse 10048 Direccin en uso.
sckAddressNotAvailable 10049 La direccin no est disponible en la mquina 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 conexin antes de
establecer SO_KEEPALIVE.
sckConnectAborted 10053 La conexin se ha cancelado al sobrepasar el tiempo de
espera o por otro error.
sckConnectionReset 10054 La conexin se ha restablecido desde el lado remoto.
sckNoBufferSpace 10055 No hay espacio disponible en el bfer.
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 conexin.
sckConnectionRefused 10061 Se ha forzado el rechazo de la conexin.
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 vlido; no hay registro de datos del tipo solicitado.

SendComplete (Evento)
Se produce cuando termina una operacin de envo.
- Sintaxis: objeto_SendComplete
- Argumentos: Ninguno

SendProgress (Evento)
Se produce mientras se estn enviando datos.
- Sintaxis: objeto_SendProgress (bytesEnv As Long, bytesRest As Long)
La sintaxis del evento SendProgress consta de las siguientes partes:
Cdigo:
Parte Descripcin
objeto Expresin de objeto que da como resultado un objeto de la lista Se aplica a.

59
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

bytesEnv Nmero de bytes enviados desde la ltima vez que se activ el evento.
bytesRest Nmero de bytes que esperan en el bfer de envo a ser enviados.

60
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Diagramas de flujo

61
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Introduccin
A continuacin 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 cdigo y
otras que son producidas por acontecimientos externos como la pulsacin de un botn o
el cambio producido en una ventana de texto del programa.
El primer diagrama de cada aplicacin muestra el tratamiento a eventos producidos
desde el men de la aplicacin, mientras que, los siguientes diagramas muestran el
tratamiento realizado a todos los dems eventos.

62
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Aplicacin scada

63
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Aplicacin cliente lectura

CLIENTE LECTURA ON

EVENTO

OnConnectWinsock1() OnDestroy()

OnInitDialog()
OnTimer(UINT nIDEvent)
OnConnectWinsock2() OnDataArrivalWinsock2(long bytesTotal)

OnDataArrivalWinsock1(long bytesTotal)

Remote? Si mensaje es
Flag PASS y Envo mensaje aceptado: Muestra consigna Inicia parmetros
Remote activados obtener al Flag Remote recibida del Cierra socket si se y variables del
Aviso por pantalla Servidor. SI NO activado, flag Servidor por destruye la
sistema
de introducir Flag Remote PASS pantalla. ventana y envia
contrasea activado desactivado y Flag obtener una peticin de
Anula Indica error en el desactivado borrado de la
reinicio socket 1
temporizador. sistema. conexin del
Flag Remote Flag obtener cliente
desactivado desactivado

64
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Aplicacin cliente escritura

CLIENTE ESCRITURA ON

EVENTO

OnConectar() OnConfirmarPassword() Volver


OnEnviar()
OnObtener()
OnActualizar()
Si el sistema esta
Conectado con conectado con el
servidor? servidor se enva PASS? Si el sistema esta
la consigna Conectado con conectado con el
NO SI servidor? servidor se solicita
NO SI
NO SI la informacin, en
caso contrario se
informa por
pantalla de que el
Conecta con el "El sistema ya Informa de que el sistema no esta
Se enva
servidor y esta conectado" sistema ya esta conectado Retorno al men
OnActualizar() NOP contrasea al
activa flag PASS NOP conectado principal
servidor
NOP

CLIENTE ESCRITURA ON

EVENTO
OnConnectWinsock1()
OnChangeConsigna() OnDestroy() OnInitDialog()
OnTimer(UINT nIDEvent)

Cierra socket si se Inicia parmetros


Valida la consigna destruye la y variables del
Si Flag PASS esta si esta dentro del ventana sistema
Pide la peticin de desactivado,
OnDataArrivalWinsock1(long bytesTotal) rango establecido
contrasea por actualiza el
parte del Servidor estado de
conexin con el
servidor por
pantalla

Dato recibido Consigna


SCADA OFF
Conectado
PASS

Se informa por Se informa por Se informa por Se actualiza por


pantalla que el pantalla la pantalla que el pantalla la
scada esta peticin de sistema esta temperatura
desconectado. introduccin de conectado con el actual del sistema
Se desconecta del contrasea. servidor.
servidor. Flag PASS Flag PASS
Se reinicia socket activado desactivado

65
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Aplicacin servidor

66
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

67
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Conclusiones

68
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Conclusiones

La aplicacin desarrollada en el proyecto es capaz de realizar el control y monitorizacin


remota de un proceso industrial a travs 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
estandarizacin, la aplicacin 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 dispondrn de una conexin de red local en planta y
necesitaran estaciones independientes conectadas a internet que puedan interconectarse de
forma segura con el proceso. Tambin se ha desarrollado una opcin para poder trabajar sin
una estacin de servidor con direccin IP esttica, en el proyecto se ha expuesto una
solucin a este problema pero existen varias soluciones eficaces y eficientes.
Tambin pueden surgir otras problemticas de falta de recursos o de cambios en la estructura
de la red, que en el proyecto se han resuelto satisfactoriamente, creando una aplicacin
donde el usuario puede ir variando los parmetros de conexin. Esta versatilidad combinada
con la facilidad de manejo de la aplicacin, 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 aplicacin donde se
podr escoger, segn el grado de privilegio del usuario y las necesidades de este, la
aplicacin ms idnea. Todas las aplicaciones cliente mantienen un formato similar para
conseguir la adaptacin rpida del usuario en la aplicacin.
Se ha intentado exponer, de forma funcional, en este proyecto los fundamentos bsicos
que conforman el eje del sistema. Estos conceptos como la funcionalidad de los sockets y
de transmisin de datos, son clave para poder entender el procedimiento del sistema.
Teniendo en cuenta la motivacin pedaggica de este proyecto, se podra realizar algunas
posibles lneas de continuacin como crear la interface necesaria para comunicar el
proceso industrial con la aplicacin scada, crear una base de datos externa de todos los
usuarios y un historial de conexiones, ampliar la consigna del proceso a ms de una
pudiendo simular el control total de un proceso industrial, posibilidad de encriptar la
informacin transmitida en red, realizar la transcripcin del cdigo a otros lenguajes
como java para crear una interface basada en http (pginas web)
Este proyecto tambin puede ser utilizado como base para realizar cualquier tipo de
implementacin de un sistema mltiple cliente servidor.
Al ir avanzando en la programacin de la aplicacin se han corregido bastantes errores
producidos en gran mayora por problemas de comunicacin 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.

69
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Gran parte del xito de este proyecto radica en el estudio anterior sobre programacin en
c, aportado en asignaturas realizadas en el transcurso de la carrera y de la informacin
obtenida en la bibliografa documentada en el apartado referencias de este documento.
Tambin ha sido de gran utilidad la informacin obtenida va internet de los diferentes
aspectos de comunicacin entre sockets que han ayudado a corregir algunos errores
aparecidos en el transcurso de la elaboracin de este proyecto.
En el anexo aadimos el cdigo de todos los archivos que se incluyen en el proyecto de
Microsoft Visual C++.

70
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Referencias

71
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

[1] Kris Jamsa y Ken Cope, Programacin 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 programacin UNIX, Prentice-
Hall.
[5] C++ Cmo programar Cuarta edicin por Deitel y Deitel, 2003.
[6] David Kruglinski, George Shepherd, Scot Wingo. PROGRAMACIN
AVANZADA CON MICROSOFT VISUAL C++ 6.0, McGraw-Hill, 2003.
[7] Kate Gregory. EDICIN ESPECIAL VISUAL C++ 6, Prentice-Hall, 1999.
[8] Microsoft Developer Network, http://msdn.microsoft.com

72
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

APLICACIN SCADA BASADA EN


COMUNICACIN TCP/IP

MANUAL USUARIO

73
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

INDICE

Configuracin del hardware___________________________________71

Aplicacin servidor________________________71

Aplicacin cliente_________________________78

Instalacin________________________________________________ 79

Servidor 79

Cliente 80

Funcionamiento de la aplicacin______________________________ 81

Servidor 82

Cliente 82

74
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

75
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Configuracin del hardware

Aplicacin servidor
Para poder utilizar correctamente la aplicacin servidor se debern tener en cuenta los
siguientes factores:

Disponemos de una Intranet?


Qu servicio de acceso a internet tiene la estacin donde reside la aplicacin?
Con qu tipo de dispositivo realizamos la conexin a Internet?
IP de la estacin dinmica o esttica?
Sistema operativo de la estacin?

Despus de realizar estas preguntas se puede observar que la configuracin del sistema
puede ser variable y que cada configuracin tendr sus diferentes pasos a seguir.
Algunas configuracines nos permitirn trabajar con un sistema ms estable, evitando
perdidas de conexin por parte del servidor e evitar errores con los datos del proceso.
La configuracin ms 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 direccin IP esttica
Dispositivos de conexin a la red con alimentacin ininterrumpida (SAI)
Acceso a internet por medio de Proxy3

Con esta configuracin la aplicacin podr funcionar perfectamente sin ningn tipo de
configuracin 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 configuracin tambin se puede ejecutar la aplicacin con
cualquier sistema operativo Windows conectado a una red local o a Internet. El gran
inconveniente de no disponer una direccin IP esttica es que con la IP dinmica la

3
Proxy hace referencia a un programa o dispositivo que realiza una accin en representacin de otro. Su finalidad ms
habitual es la de servidor proxy, que sirve para permitir el acceso a Internet a todos los equipos de una organizacin
cuando slo se puede disponer de un nico equipo conectado, esto es, una nica direccin IP.

76
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

direccin cambia a voluntad del proveedor, normalmente cuando reseteamos nuestro


router/modem.

Configuracin para trabajar con IP dinmica

La solucin planteada aqu es usar un servicio de nombrado dinmico, es decir que sea
capaz de trabajar con una IP dinmica. 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 dinmico (estos son slo algunos de
ellos):

No-IP

ZoneEdit

DynDNS

Adems se necesita un software en el sistema operativo que se comunique con el


servicio de nombrado dinmico.

A continuacin se describe, a modo de ejemplo, una configuracin del servidor:

77
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 sesin 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 aplicacin y


observar la direccin que aparece en pantalla o ir a la aplicacin Ms-Dos de Windows
(Inicio-Todos los programas-Accesorios-Simbolo del sistema). Dentro de la aplicacin
ejecutar ipconfig y aparecer una ventana como esta:

La direccin actual del sistema de este caso sera 192.168.1.2

Configuracin 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 contrasea. Por defecto es 1234 en ambas
casillas, si no pueden ingresar con estos datos, van a tener que conseguirlos ya que no

78
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 opcin NAT de la columna Advanced Setup. Clickeamos ah.

4) Nos aparecer la pantalla NAT - Mode.

79
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Seleccionamos la opcin SUA Only y clickeamos en Edit Details de esa misma opcin.

5) Aparece la pantalla con los re direccionamientos. Hay 12 casillas.

80
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Ahora viene la parte ms sencilla. En la columna Start Port No. vamos a escribir el
nmero del puerto en donde se comenzar a abrir. En la columna End Port No.
escribiremos el nmero 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 slo puerto, escribo el mismo nmero en ambas casillas.
En la columna IP Adress debemos escribir la direccin IP interna de nuestra PC, es
decir, la direccin IP de nuestra PC en la red (no es la IP pblica). Para descubrir la IP
actual de nuestro sistema seguir los pasos detallados en la configuracin anterior.

sa es la direccin IP que debemos ingresar en la tercer columna, tal como aparece en la


consola de MS-DOS. Por ejemplo, si nuestra aplicacin utiliza los puertos 4662 y 4672,
y nuestra direccin IP interna es 192.168.1.2, quedara de la siguiente manera:

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

81
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Aplicacin Cliente
La configuracin del sistema para el correcto funcionamiento de la aplicacin cliente es
cualquiera que posea una conexin a internet y un sistema operativo Windows. Tener en
cuenta tambin que las aplicaciones de antivirus y cortafuegos nos permitan el acceso al
exterior de la aplicacin.

82
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Instalacin

Servidor
Para instalar la aplicacin Servidor bastara con ejecutar la aplicacin
PFC-EGP-Servidor.exe

Y seguir las instrucciones que nos aparecern en pantalla

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

Cliente
Para la instalacin de la aplicacin cliente se realizarn los mismos pasos que en la
instalacin de la aplicacin servidor.

83
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Funcionamiento de la aplicacin
El software realizado (Cliente.exe, Servidor.Exe) se debe instalar en un ordenador PC
compatible con el sistema operativo Windows.
Dependiendo de cul sea la ubicacin se instalara una aplicacin o otra:
En el ordenador donde est conectado el proceso industrial instalaremos la aplicacin
Cliente (Scada), esta aplicacin se encargara de captar los datos del sensor y enviar la
consigna deseada.
En el ordenador donde reside el ordenador Servidor con conexin al exterior
instalaremos la aplicacin Servidor.exe, esta aplicacin se encargara de guardar los datos
del proceso y enviarlos debidamente a los destinatarios, tambin enviara la consigna
deseada al ordenador del proceso cuando tenga activada esta opcin.
En todos los dems ordenadores pertenecientes a la red LAN o WAN se podr instalar la
aplicacin cliente y trabajar como lectura o escritura, la diferencia entre estas dos
aplicaciones reside en el hecho de que lectura slo puede leer los datos del sensor
mientras que escritura puede leer y enviar la consigna deseada cuando el ordenador del
proceso tenga activada esta opcin.
La aplicacin escritura slo funcionar desde una nica ubicacin, aunque esta se puede
variar dependiendo de las necesidades de la planta, el motivo de esta configuracin es la
de evitar posibles datos errneos en la consigna del proceso.
A continuacin se mostraran todas la pantallas detalladas de los mens pertenecientes a
cada aplicacin.

84
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Servidor

Cliente

85
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Aplicacin Scada:

Cliente lectura:

86
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

Cliente escritura:

87
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

ANEXOS

88
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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)


{

89
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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[] =

90
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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);
}

91
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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.

92
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

#endif //
!defined(AFX_MSWINSOCKCONTROL_H__5F5F6292_64DE_48DD_A382_A558E468340A__INCLUDED_)

93
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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

94
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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)
{

95
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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

96
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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_)

97
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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)
{

98
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

//{{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

99
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

SetIcon(m_hIcon, FALSE); // Set small icon

// Inicializamos las variables del sistema y la informacin 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 direccin 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();
}
}

100
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

// 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 botn 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 peticin de conexin del socket 1

101
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

void CServerDlg::OnConnectionRequestWinsock1(long requestID)


{
CString IP;
m_socket1.Close();
vtHost.vt=VT_BSTR;
vtHost.bstrVal=IP.AllocSysString();
m_socket1.Accept(requestID); //Aceptamos conexin
Socket1=TRUE; //Activamos flag de conexin con scada
CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT5); //captamos contenido edit
pEdit->SetWindowText("Conectado");

//Evento perteneciente a la recepcin 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
conexin 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 conexin 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

102
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

//Inicializacin de los sockets

void CServerDlg::InitSocket()
{

//////CONFIGURACIN 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 mquina
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();

103
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

/////////Creacin 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();
}

//Actualizacin temperatura actual

void CServerDlg::OnTactual()
{

CString Data;
CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT1); //captamos contenido edit
pEdit->GetWindowText(Data);

//Evento perteneciente a la peticin de conexin del socket 2

void CServerDlg::OnConnectionRequestWinsock2(long requestID)


{

104
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

long Port;
CString IP;
BOOL encontrado=FALSE;

//Si hay conexin 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 conexin 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 recepcin 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&&Passwor
d==TRUE)
{
CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT2);
pEdit->SetWindowText(mensaje);
}

//Realizamos peticin de password al cliente

if(mensaje=="PASS")
{
VARIANT vtDato;

105
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

CString Dato;
Dato = "PASS";
vtDato.vt=VT_BSTR;
vtDato.bstrVal=Dato.AllocSysString();
m_socket2.SendData(vtDato);
}

//Establecemos conexin 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 desconexin 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 modificacin de la consigna del sistema

void CServerDlg::OnChangeConsigna()
{

106
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 peticin de conexin del socket 4

void CServerDlg::OnConnectionRequestWinsockClienteR(long requestID)


{
long Port;
CString IP;
BOOL encontrado=FALSE;

//Si el servidor no esta ocupado atendemos a la peticin de conexin 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 recepcin 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;

107
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 conexin

vtHost.vt=VT_BSTR;

108
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 informacin
}

//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 botn validar

void CServerDlg::OnValidarPSWRW()
{
CEdit* pEdit2 = (CEdit*) GetDlgItem(IDC_EDIT3); //captamos contenido edit
pEdit2->GetWindowText(PasswordRW);
AfxMessageBox ("Contrasea 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();

109
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

//Evento perteneciente a la peticin de conexin del socket 3

void CServerDlg::OnConnectionRequestWinsockClienteRDatos(long requestID)


{
//Si el servidor no esta ocupado enviamos la informacin 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 recepcin 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 botn cambiar contraseas

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);

110
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 ("Contraseas 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 botn 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 botn 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 botn habilitar/deshabilitar cliente 2

void CServerDlg::OnEnableClient2()
{
if(EnableClient2)
{
EnableClient2=FALSE;
AfxMessageBox ("Cliente deshabilitado 2");
}
else
{
EnableClient2=TRUE;
AfxMessageBox ("Cliente habilitado 2");

111
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

//Evento perteneciente al botn 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 botn 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 peticin de conexin 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 desconexin

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("");

112
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

}
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 mquina
servidora
m_socket2.Listen(); //prepara para la escucha
}
}

//Evento perteneciente al cierre del socket 5

void CServerDlg::OnCloseWinsock5()
{
m_socket5.Close();
m_socket5.Listen();

113
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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;

114
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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_)

115
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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);
}

116
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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_)

117
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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

118
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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)
{

119
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

// 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;
}

120
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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_)

121
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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);

122
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 conexin 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);

////Simulacin Proceso industrial/////

TA = atoi( Tact );
if (TA!=Consigna||TA!=23)

123
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

{
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 botn 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 variacin 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);

124
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 configuracin 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 direccin 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;

125
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 destruccin 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

126
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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

127
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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_)

128
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 "Conexin 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 conexin";
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()

129
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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_)

130
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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));

131
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

//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 conexin por pantalla
SetTimer(1, 500, NULL); //Activacin 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 conexin 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 conexin 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 introduccin de
contrasea 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 conexin con el servidor

if (estado == "Conectado")
{
AfxMessageBox ("El sistema ya esta conectado");
}
else if (estado =! "Conectado")

132
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

{
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 conexin con el servidor

if (estado != "Desconectado"&& estado != "Cerrado")


{
AfxMessageBox ("El sistema ya esta conectado con la IP establecida. Para
establecer una nueva direccin 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;

133
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 introduccin de contrasea

if(mensaje=="PASS")
{
PASS=TRUE;
AfxMessageBox ("Confirmar Password");
}

//Avisamos por pantalla de la introduccin de contrasea

if(mensaje=="Conectado")
{
AfxMessageBox ("Password correcto");
CEdit* pEdit1 = (CEdit*) GetDlgItem(IDC_EDIT4);
pEdit1->SetWindowText("Conectado");
PASS=FALSE;
}

//Avisamos de la desconexin 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;

134
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 botn 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 botn 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 variacin 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);

135
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

pEdit->SetWindowText("Valor de consigna valido");


Consigna = atoi( Dato );
}
}

//Evento llamado cuando se produce la destruccin 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();

136
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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_)

137
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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);

138
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 configuracin de puertos y IP del servidor

void CCLectura::OnActualizar()
{
CString estado;
CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT4);
pEdit->GetWindowText(estado);

139
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

if (estado != "Desconectado")
{
AfxMessageBox ("El sistema ya esta conectado con la IP establecida. Para
establecer una nueva direccin 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 conexin con el servidor

if (estado == "Conectado")
{
AfxMessageBox ("El sistema ya esta conectado");
}
else if (estado =! "Conectado")
{

140
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 conexin 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;

141
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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 botn 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 conexin 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;

142
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

CEdit* pEdit = (CEdit*) GetDlgItem(IDC_EDIT2);


pEdit->SetWindowText(mensaje); //Se muestra por pantalla la temperatura actual
Obtener=FALSE;
}

//Evento llamado cuando se produce la destruccin 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 desconexin del cliente
AfxMessageBox ("Si el sistema esta conectado con el servidor va a ser
desconectado");
CDialog::OnDestroy();

143
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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();

144
APLICACIN SCADA BASADA EN COMUNICACIN TCP/IP ESTEVEGRAUPINA

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_)

145

Vous aimerez peut-être aussi