UNIVERSIDAD AUTONOMA METROPOLITANA

Anuncio
UNIVERSIDAD AUTONOMA METROPOLITANA
UNIDAD:
lztapalapa
’
DIVISION:
Ciencias Basicas e Ingeniería
’
CARRERA:
Licenciatura en Computación
MATERIA:
Proyecto Terminal I y II
’
’’
TITULO:
Interfaces de Programación de Aplicaciones utilizando COM
FECHA:
12 de Julio de 1999
-
./ALUMNOS:
ASESOR:
e
u
Cortes Torres Isabel Cristina
94219468
Juárez Olivo Adriana Berenice
94217242
López Ponce Ramiro Antonio
93220496
d a n d o Castro Careaga
Departamento de Comoutación
Interfaces de Programación de Aplicaciones
utilizando COM
COM desde Visual Basic
Adriana Juárez Olivo
Isabel Cortes Torres
Ramiro López Ponce
División de Ciencias Básicas e Ingeniería
Universidad Autónoma Metropolitana
Unidad lztapalapa
Asesor de Proyecto
Ing. Luis Fernando Castro Careaga
Departamento de Computación
Universidad Autónoma Metropolitana
Unidad lztapalapa
Interfaces de Programación de Aplicaciones utilizando COM
COM desde Visual Basic
Adriana Juárez Olivo
Isabel Cortes Torres
Ramiro López Ponce
El contenido de ésta obra corresponde a la
documentación del proyecto de la Licenciatura en Computació I y II
llevado a término por los autores, de acuerdo
con el plan de estudios vigente de la
Universidad Autónoma Metropolitana
Impreso en México
Esta obra se terminó de
imprimir en Julio de 1999
en las instalaciones del Edificio T de
Ciencias Básicas e Ingeniería de la
Universidad Autónoma Metropolitana
Unidad lztapalapa
Av. Michoacán y la Purísima
Col. Vicentina
Delegación lztapalapa
09340 México, D.F.
Se imprimieron 2 ejemplares
Agradecimientos y Dedicatorias
Existieron muchas personas, las cuales contribuyeron a mi formación profesional.
Principalmente quiero dar las gracias a mi padre por su incondicional apoyo y amor, sobre
todo por la gran fe que siempre ha tenido en mi; a mi madre por sus consejos y
sugerencias y a mi tía por brindarme la ayuda y serenidad que en sus momentos necesite.
Ellos fueron quienes hicieron esto posible:
Juan Manuel Juárez Valencia. mi padre
Luz María Olivo González, mi madre
María Teresa Olivo González, mi tía
Especialmente a una persona que compartió conmigo una de las fases más importantes
de mi vida y que gracias a su ayuda y motivación logre concluir mis estudios
profesionales:
Alvaro Israel Ruiz Rivera, mi novio, amigo y compañero.
También quiero agradecer a Dios, por permitirme llegar hasta donde hoy estoy.
Gracias a todos y a ustedes dedico este triunfo.
Adriana Berenice Juárez Olivo
Agradecimientosy Dedicatorias
on muchas las personas que contribuyeron con su tiempo y esfuerzo a mi formación
profesional. En particular quiero dar gracias a mi Madre por su incondicional apoyo y su
admirable generosidad y comprensión. A todos mis hermanos que sin su tolerancia,
paciencia y ayuda esta tarea hubiera sido mucho más difícil y sobretodo por todos aquellos
consejos y sugerencias que me dieron en su momento. Quiero agradecer a mis amigos por
compartir momentos de fracaso, adversidad y de éxito durante la carrera. También estoy en deuda
con mis profesores por su guía, por su disposición de compartir sus conocimientos y los beneficios
de su experiencia, en especial de mi Asesor, por su incomparable altruismo y comentarios que no
son más que un aliciente para continuar con mi superación tanto profesional como personalmente.
S
inalmente estoy profundamente agradecida con Dios por haberme permitido llegar hasta
donde estoy. Gracias a El soy lo que soy.
F
C
on admiración, respeto y cariño, a todos ellos, les dedico este esfuerzo. Espero nunca
defraudar la confianza que han depositado en mí.
Isabel Cristina Cortés Torres.
Agradecimientos y Dedicatorias
A Dios, por permitirme estar aquí
A mi Mamá por su gran voluntad y amor
A mis Hermanos por que juntos caminamos
A Claudia por su amor incondicional
A mi Familia por el gran apoyo recibido
A mis Amigos por el tiempo vivido
A las sonrisas de Priscila, Neftali y Gabriel
Ramiro López Ponce
lndice
INTRODUCCION
1
Capitulo I MODELO CLlENTElSERVlDOR
4
1. I Cliente
4
I.
I.
1 Características
4
I .I.2 Sistemas Operativos
4
1. I .3 Acceso a las Bases de Datos
5
1.2 Servidor
1.2.1 Características
6
6
1.2. I.
1 Multiprocesamiento
6
1.2.I.2 Multihilos
7
1.2.1.3 Arreglos de discos
7
1.2.2 Clasificación de Servidores
8
1.2.2.1 Servidor de archivos
8
1.2.2.2 Servidor de aplicaciones
8
1.2.2.3 Servidor de bases de datos
8
1.3. Definición de Cliente/Servidor
9
1.4. Características generales de Cliente/Servidor
10
1.4.1 Mantenibilidad
10
1.4.2 Modularidad
10
1.4.3 Adaptabilidad
10
1.4.4 Escalabilidad
11
1.4.5 Portabilidad
11
1.4.6 Estándares/Sistemas abiertos
12
1.4.7 Autonomía
11
1.4.8 Flexibilidad
11
1.5.Comunicación Cliente/Servidor
12
1.5.1 Modelo Conversacional
12
1.5.2 Modelo de Mensajes
13
1.5.3 RPC's
13
1.6. Costos y Beneficios de Cliente/Servidor
14
1.7 Beneficios de la Arquitectura Ciiente/Servidor
15
1.8 Desventajas de la Arquitectura Cliente/Servidor
15
CAPITULO II CONCEPTOS GENERALES COM Y DCOM
17
2.1 Introducción
17
2.2 Creando aplicaciones dimensionables con Windows NT y DCOM
17
2.3 Neutralidad de los Lenguajes de Programación
19
2.4 Gestión de la conexión
19
2.5 Interfaces múltiples
19
2.6 independencia en la ubicación y equilibrio de carga
20
2.7 Seguridad frente a los fallos y tolerancia a los errores
20
2.8 Integración de base de datos
21
2.9 Resumen
22
Capitulo 111 COMUNICACIÓN CLIENTE SERVIDOR
BAJO EL CONCEPTO DE COM
3.1 Antecedentes
23
23
3.2 Objetos
23
3.3 Interfaces
23
3.4 ldentificadores en COM
27
3.5 interface estándar
27
3.6 Interfaces Personalizados
29
3.7 El compilador MlDL
30
Capitulo IV CREACIÓN DE UN OBJETO COM
Y USO DE SUS INTERFACES
4.1 Antecedentes
32
32
4.2 GUiD's y Registro
33
4.3 Módulos componentes de clases e interfaces
34
lndice
4.4 Obteniendo otra interface con Querylnterface
34
4.5 Controlando el ciclo de vida del objeto
35
4.6 Interfaces que permiten interoperabilidad
36
4.7 Clase objeto
37
4.8 lmplementado la clase objetos
38
4.9 lmplementando los métodos de la clase objeto
39
Capitulo V IMPLEMENTACIÓN DEL OBJETO
42
5.1 lmplementando el propio objeto
42
5.2 El diseño de CmyObject
42
5.3 lmplementando interfaces multiples usando herencia multiple
43
5.4 lmplementando a Querylnterface
47
5.5 lmplementando a AddRef y Release
47
5.6 El constructor y destructor
48
5.7 lmplementando una interface propia
50
5.8 Contruyendolo
51
5.9 El objeto clase y la fabrica de clases
53
5.9.1 El objeto clase
53
5.9.2 Porque existe un objeto clase
54
5.9.3 Otra forma de crear objetos y cuando usarla
55
5.9.4 lmplementando el objeto clase
55
5.9.5 Como es creado este objeto clase
56
5.9.6 Como CoGetClassObject obtiene el objeto clase
56
5.9.7 lmplementando los métodos del objeto clase
57
5.9.7.1 1Unknown::AddRef y 1Unknown::Release
57
5.9.7.2 lUnknown::Querylnterface
58
5.9.7.3 1ClassFactory::Createlnstance
59
5.9.7.4 1ClaccFactory::LockServer
60
5.9.7.5 DllCanUnloadNow
60
5.9.8 Usando el objeto desde Visual Basic
60
lndice
5.9.9Usando el objeto desde Visual J++
Capitulo VI AMBIENTE CLIENTEiSERVIDOR BAJO COM
63
65
6.1Antecedentes
65
6.2Clientes y Servidores COM
65
6.3La Librería COM y el Manejo de Control de Servicio
66
6.4Arquitectura para objetos distribuidos
66
6.5Objetos Conectables y Eventos
67
6.6Transferencia de Datos Uniforme
70
6.7Formatos de datos y medios de transferencia
71
6.8Responsabilidades de una aplicación COM
72
Capitulo VII APLICACI~N
73
7.1Objetivo
73
7.2Descripción
73
7.3Descripción del Diseño
73
7.3.1Base de Datos
73
7.3.2Cliente
74
7.3.3Servidor
78
7.4 Implementación
82
7.4.1Creación de la aplicación Cliente
82
7.4.2Creación de la aplicación Servidor
7.4.3Generación de Setup para la aplicación
88
Cliente-Servidor Remote Automation Ó COM
7.4.3.1Creación del setup para el Servidor
90
7.4.3.2
Creación del setup para el Cliente
92
90
CONCLUSIONES
95
BlBLlOGRAFlA
98
Introducción
Dos décadas atrás, el procesamiento de datos se basaba en el uso de poderosos
mainframes, el acceso a éstos se llevaba a cabo por medio de rudimentarias terminales
que sólo permitían la comunicación con el procesador central. Los métodos para el
procesamiento de la información resultaban ser arduos y complejos debido a la
centralización de los recursos y a las hostiles interfaces de usuarios. Así que cuando
aparecieron las primeras computadoras personales, cerca de los años ochenta, su
crecimiento fue inmediato debido a su facilidad al acceso de los datos, así como por sus
interfaces amigables.
Sin embargo, las PC siguieron siendo incapaces de manejar el procesamiento de
datos necesarios para las grandes empresas. Las redes de área local (LAN, Local Area
Network) dieron una solución a este problema interconectando PC y mainframe. Esto es,
las PC son utilizadas como terminales inteligentes (amigables), las cuales facilitan la
conexión del usuario con el procesador central (MAINFRAME).
Actualmente, tanto las PC como las redes de área local son usadas en casi la
totalidad de las empresas; las PC permiten contar con una variedad de procesadores de
texto, hojas de cálculo y software de basa de datos, mientras que el uso de redes de área
local permite compartir archivos y periféricos (impresoras, modems, unidades de respaldo,
etc.). Sin embargo, la mayoría de las aplicaciones de “misión crítica” pertenecen en
“manos” de los mainframes (y computadoras). El objetivo de la industria de redes y en
particular la industria de los servidores de base de datos se centra en “bajar” las
aplicaciones existentes en los mainframes hacia servidores PC y LAN, usando para ello la
arquitectura cliente/servidor. Esto tiene como consecuencia el desarrollo de nuevos
sistemas operativos enfocados hacia redes de computadoras y desarrollo de manejadores
de base de datos capaces de soportar el esquema cliente/servidor.
El término cliente/servidor se utiliza frecuentemente como sinónimo del
procesamiento cooperativo o distribuido. Pero el procesamiento distribuido no es nuevo,
desde los años 70 existen sistemas de computo que pueden considerarse distribuidos,
pero se desarrollaban de tal manera que la distribución de las funciones y los datos
quedaba implícita en el diseño y código del programa, como también en las
comunicaciones entre las aplicaciones. Esto dio como resultado aplicaciones distribuidas
de forma cooperativa con una estructura muy rígida. Los programas y datos se
encontraban asociados unívocamente, por lo que los datos no se accesaban de una
manera global desde las diferentes aplicaciones, sino como parte integral de éstas
mismas.
Actualmente, las computadoras personales y los paquetes de software de
aplicaciones proliferan comercialmente. Las estaciones de trabajo están conectadas a
redes de área local (LAN) mediante las cuales se comparten aplicaciones y datos. Las
nuevas tecnologías de distribución de funciones y datos en una red permiten desarrollar
aplicaciones distribuidas de una manera trasparente, de forma que múltiples
1
Introducción
procesadores puedan ejecutar partes distintas de una aplicación. Si se elige una
adecuada infraestructura de sistemas distribuidos y herramientas de desarrollo, las
aplicaciones resultantes podrán transladarse a plataformas de diferentes proveedores.
El proceso distribuido se reconoce actualmente como el nuevo paradigma de los
sistemas de información. Este cambio ha surgido fundamentalmente como consecuencia
de importantes factores (negocio, tecnología, proveedores), y se apoya en la existencia de
una gran variedad de aplicaciones estándares y herramientas de desarrollo fáciles de usar
que soportan un entorno informático distribuido. Esta infraestructura no debe ser
implementada sólo por razones tecnológicas o de moda, deberá utilizarse para desarrollar
o rediseñar aplicaciones que soporten los objetivos de la empresa. Sin embargo, la
migración de aplicaciones ya existentes sin modificar su funcionalidad, puede acarrear
costos substanciales y no producir los resultados deseados.
Las condiciones que sugieren la implantación del ambiente cliente/servidor en una
empresa son:
0
0
0
0
Cambios estructurales y organizativos.
Cambios en los organigramas con mayor delegación en personas y
departamentos.
Respuesta a la dinámica del mercado.
Cambios en los procesos de negocio.
El mundo en constante cambio
Procesos de
negocios flexibles
Organización flexible
Ambiente de cómputo flexible
‘0s
+2=-
Permite a% empresa obtener una
ventaja sobre sus competidores
en un mercado con cambios
constantes
2
Introducción
Las razones que impulsan el crecimiento de las aplicaciones cliente/servidor son:
0
0
0
0
La demanda de sistemas más fáciles de usar, que contribuyan a una mayor
productividad y calidad.
La relación precio/rendimiento de las estaciones de trabajo y de los servidores.
La creciente necesidad de acceso a la información para la toma de decisiones y el
soporte de los procesos mediante aplicaciones más ajustadas a la estructura
organizativa de la empresa.
La utilización de nuevas tecnologías y herramientas de alta productividad más aptas
para la dinámica del mercado.
Enfocado correctamente, el modelo cliente/servidor
permite ejecutar las
aplicaciones en la plataforma informática más adecuada para maximizar el beneficio
operativo. También significa la posibilidad de reubicar funciones y datos, es decir,
modificar los procesos de negocios sin alterar la lógica de la aplicación. La selección de
herramientas adecuadas conduce a un desarrollo acelerado de las aplicaciones y
mediante la reutilización de servidores puede reducirse notablemente la tarea de
mantenimiento.
3
Cap. 1. Modelo Cliente /Servidor
En este Capitulo se explicarán los conceptos
Cliente y Servidor,
mencionando las principales características de cada uno de ellos para describir
finalmente el Modelo Cliente/Servidor, presentando sus ventajas y desventajas.
1.1 Cliente
AI software para cliente se le llama “Front-end” puede estar en los más
diversos ambientes como UNIX, MSDOS, WINDOWS, MACs, etc., permite al
usuario final interactuar con la computadora y contiene al menos alguna aplicación
lógica. La mayoría del software cliente proporciona la característica popular de una
interface de usuario gráfica (GUI) lográndose un uso amigable.
1.I.ICaracterísticas
En la arquitectura ClienteíServidor un cliente es un proceso que interactúa con el
usuario y cuenta con las siguientes características:
0
Un Front-end puede encontrarse en una amplia gama de software. Puede ser tan
sencillo como una herramienta existente de usuario final como una hoja de calculo o
tan complejo como un programa en C o C++.
0
Presenta una interfaz al usuario (U1 User Interface), la cual tiene como objetivo enviar
y recibir información del Servidor.
Debido a que una arquitectura Cliente/Servidor puede consistir de múltiples clientes,
es posible que múltiples interfaces puedan correr simultáneamente, cada cliente
cuenta con su propia interfaz.
0
Crea uno o más queries en un lenguaje predeterminado para ser enviados al Servidor.
El Cliente y el Servidor pueden comunicarse a través de un lenguaje estándar.
0
Se comunica hacia el Servidor a través de un proceso de comunicación. Idealmente
este proceso es transparente al usuario.
0
Los Front-ends continúan incorporando características orientadas a objetos.
1.I.2 Sistemas Operativos
El primer propósito de un sistema operativo es proporcionar a las aplicaciones los
recursos de hardware de los equipos de cómputo como memoria, almacenamiento de
disco, etc., y manejo con los dispositivos externos como impresora, scanner, etc.
La transportabilidad de nuestras aplicaciones en un Front-end depende
primordialmente de los sistemas operativos en los que sea capaz de trabajar.
4
Cap. 1. Modelo Cliente /Servidor
Actualmente nos encontramos en el mercado con una gran gama de sistemas
operativos y en gran medida las empresas cuentan con diversos equipos, teniendo como
consecuencia, también una gran diversidad de sistemas operativos.
En las empresas con la diversidad de plataformas, antes mencionadas, no les
conviene “casarse” con un único sistema operativo y mucho menos propietario, por io que
se recomienda desarrollar las aplicaciones Cliente en un Front-end que trabaje sobre una
gran variedad de sistemas operativos, esta característica nos ahorrara tiempo de trabajo
ya que al exportar nuestra aplicación de un sistema operativo a otro serán mínimas las
modificaciones o quizás nulas.
Entrando en detalles con los sistemas operativos debemos de tener en cuenta
cuantas diferentes configuraciones de hardware pueden soportar dichos sistemas
operativos.
Dando algunos ejemplos, el MS-DOS sólo puede correr en PC‘s, Windows
también fue hecho para trabajar en PC‘s, a diferencia de UNiX que puede trabajar en la
gran mayoría de computadoras ya sea PC’s, WorkStations, Minis, etc. dándole la
característica de portabilidad.
También hay que tomar en cuenta que el sistema operativo donde corra nuestra
aplicación incluya interfaces de usuario gráficas como Windows, OS/DOS Warp, Solarys,
etc., con el fin de facilitar el manejo de la aplicación al usuario final [DAW93].
1.1.3 Acceso a las Bases de Datos
Uno de los usos más populares de los sistemas Cliente/Servidor es el de permitir a
los usuarios finales el acceso a los datos de un gran almacén como el de una base de
datos. Muchas herramientas query ayudan a llevar a cabo este propósito.
El desarrollo de las herramientas query en primera instancia se pensaba que iban
en contra de la producción de bases de datos mainframe, sin embargo actualmente es
frecuente que se les instale un manejador de base de datos relaciona1 (RDBMS) donde se
le pueda accesar fácilmente por medio de SQL o herramientas generadoras de SQL
[COD90].
Además de los RDBMS también existen varias bases de datos desarrollados para
trabajar sobre PC’s,las cuales no suelen ser sistemas relacionales, pero por lo general
permiten a los usuarios expresar un requerimiento en términos de SQL y posteriormente
el software convierte el requerimiento en el formato que la base de datos pueda entender.
5
Cap. 1. Modelo Cliente /Servidor
1.2 Servidor
En la arquitectura Cliente/Servidor, el Servidor “back-end” maneja los recursos de
información, es decir, almacena, recupera y protege los datos. El Servidor revisa los datos
requeridos y si es necesario, genera y manda los datos solicitados a un Cliente u otro
Servidor.
1.2.1 Características
Un Servidor es un proceso o un conjunto de procesos, que debe existir en una
máquina y su objetivo será el de proveer un servicio a uno a más clientes, posee las
siguientes características:
0
Un Servidor da un servicio a los clientes. Un servicio otorgado por un Servidor puede
requerir de un apoyo mínimo por parte de éste o bien de un cálculo intenso como
podrían ser Servidores de base de datos o Servidores de procesamiento de imágenes.
0
Un Servidor ideal esconde su estructura al Cliente y al usuario, es decir, se establece
una comunicación transparente entre el usuario y el Servidor, sin importar la
plataforma del Servidor (hardware y software), así como también de la tecnología de
comunicación que se utilice.
0
Cuando se elige una máquina como Servidor debe de contemplarse algunas
características técnicas como el multiprocesamiento, multihilos y arreglos de discos.
Hay que tomar en cuenta que la mayoría de las veces, si no es que siempre, los
Servidores juegan un papel crítico, donde una falla podría ser catastrófica para
cualquier tipo de empresa, es por eso que además deben de contemplar redundancia
de algunos componentes tales como manejadores de discos, fuente de energía,
discos espejo, etc.
1.2.1.I
Multiprocesamiento
Los fabricantes están incluyendo múltiples procesadores en su hardware para
incrementar la velocidad de procesamiento. Varios procesadores nos permiten realizar el
multiprocesamiento simétrico o funcional.
Con el multiprocesamiento simétrico se puede asignar dinámicamente una tarea a
un procesador. Los recursos de procesamiento son maximizados. Cuando hay una tarea
por realizar un procesador desocupado la lleva a cabo.
El multiprocesamiento funcional permanentemente asigna un conjunto de tareas a
un procesador. Consecuentemente, un procesador puede “flojear” cuando otro puede
estar sobrecargado de trabajo.
6
Cap. 1. Modelo Cliente /Servidor
1.2.1.2 Multihilos
Un hilo es la unidad más pequeña de ejecución que el sistema puede listar. Cada
apuntador, una prioridad, el estado del CPU y una
hilo consiste de una pila, un
entrada en la lista de espera del sistema.
Un hilo puede ser bloqueado, agregado para ejecución o ejecutado. Los hilos se
comunican a través de mensajes y compiten por adueñarse de varios semáforos los
cuales controlan la asignación de recursos de cómputo.
Los sistemas operativos antiguos llevaban a cabo la multitarea para crear múltiples
procesos, pero esto desarrollaba overhead, sin embargo con el ambiente de multihilos, un
proceso es dividido en tareas independientes ejecutables. Estos hilos colectivamente
realizan el trabajo permitiendo a las aplicaciones realizar muchas tareas simultáneamente
[DAW93].
1.2.1.3Arreglos de discos
Los arreglos de discos son de gran utilidad para el usuario, debido a que pueden
recuperarse de alguna falla reemplazando el manejador de disco dañado estando el
Servidor en línea.
En un ambiente multiservidor, los Servidores que atienden a un determinado
número de clientes se comunican entre sí transparentemente, sin que el Cliente se de
cuenta de esto, por lo que, en un ambiente de procesamiento distribuido, el Cliente no
podrá ser capaz de localizar al Servidor o Servidores que los atienden.
De este modo, una arquitectura Cliente/Servidor divide una aplicación en procesos
independientes, los cuales son procesados en máquinas separadas que se encuentran
conectadas a través de una red. Entre más avanzado sea el sistema operativo de red más
se reducirán, en código, el tamaño de los procesos por ejecutar. Por ejemplo, Microsoft
LAN Manager da una amplia gama de funciones para la implementación de un sistema
Cliente/Servidor, es decir, el sistema corre soportado por las funciones dadas por
Microsoft LAN Manager, lo cual reduce el tiempo de desarrollo. Si el mismo sistema se
implementara en un sistema operativo de red que únicamente provee de las posibilidades
de compartir archivos y periféricos, el código de las aplicaciones sería fácilmente el triple.
Los Servidores pueden ser computadoras de propósito general, especializadas
(para hacer eficientes ciertas tareas), o bien, computadoras con la capacidad de
multitasking. Cualquier actividad que puede ser catalogada de uso general o reutilizable
(comunicaciones, cálculos numéricos intensos, mail/fax, etc.) es un candidato para ser
Servidor.
7
Cap. 1. Modelo Cliente /Servidor
1.2.2 Clasificación de Servidores
El Servidor fue desarrollado para compartir periféricos costosos como impresoras
láser, lectores de CD ROM, etc. Además de los periféricos, también se desarrollo para
compartir los datos y en cuanto a esto se pueden clasificar los Servidores como[BOC94]:
1.2.2.1 Servidor de archivos
Los Servidores de archivos están muy orientados a I/O (entradas y salidas). Estos
Servidores colocan gran cantidad de información en sus sistemas de almacenamiento y
pasan los datos sobre una red. Cuando los datos de un archivo son solicitados, el
Servidor transmite todos los registros al Cliente, saturando de esta forma las redes.
Debido a que el Servidor manda todo el archivo del cual se requiera alguna
información y no solamente los registros especificados, éste debe tener gran capacidad y
un muy rápido acceso al disco duro.
1.2.2.2 Servidor de aplicaciones
Este tipo de Servidor se caracteriza por prestar servicios similares a los que presta
un mainframe. Cuando las aplicaciones de un mainframe son cambiadas a otra plataforma
tratando de reducir los costos, una de las opciones consiste en instalas las aplicaciones
sobre una máquina menos grande que corra el mismo software.
1.2.2.3 Servidor de bases de datos
Este es el uso más típico de Servidor. Las aplicaciones corren sobre los clientes.
El Servidor de base de datos acepta requerimientos y pasa el resultado al Cliente.
La función de manejo de datos es del Servidor y el Cliente se encarga de ejecutar
una aplicación específica.
El Servidor de base de datos mejora el manejo de requerimientos y solo envía al
Cliente los datos que satisfacen el requerimiento. Esto es más eficiente en términos de la
carga de la red que una arquitectura file-server.
Mediante herramientas SQL se pueden procesar los registros en conjunto, una
aplicación con una sencilla instrucción de SQL puede recuperar o modificar un conjunto
de registros del Servidor.
8
Cap. 1. Modelo Cliente /Servidor
1.3. Definición de ClientelSewidor
Como primer paso se requiere conocer el término Cliente/Servidor, el cual
nos ayudará a comprender su significado, cada autor contempla su propio
concepto sin embargo todos tienden a coincidir. A continuación se listan algunas
definiciones:
La arquitectura Cliente/Servidor es una arquitectura de procesamiento en la
cual una aplicación es patticionada a través de múltiples procesadores, los cuales
cooperan de una manera unificada para completar un proceso como una tarea.
La computación Cliente/Servidor es un modelo de cómputo en el cual una
aplicación es particionada entre múltiples procesadores (front-end y el back-end), los
procesadores cooperan (transparente al usuario) entre sí para completar el procesamiento
como una sola tarea unificada. Los productos para este ambiente permiten administrar a
los procesadores para que juntos realicen una misma tarea dando la ilusión de un solo
sistema. Los recursos compartidos se encuentran colocados como Servidores, los cuales
ofrecen uno o más servicios. Las aplicaciones son colocadas como clientes, los cuales
accesan los servicios autorizados. La arquitectura es recursiva, esto es, que un Servidor
puede transformarse en Cliente y realizar peticiones de servicio hacia otro Servidor en la
red.
“Cliente/Servidores un diseño de aplicación enfocada en la descomposición de un
sistema de información dentro de un número pequeño de funciones del Servidor,
ejecutándose sobre una o más plataformas, que proporcionan servicios de uso común a
un número grande de funciones Cliente, que están interconectadas y realizan trabajos
definidos sobre los servicios comunes proporcionados por las funciones Servidor”
[vAU94].
“En la computación Cliente/Servidor uno o más clientes y uno o más Servidores
bajo un sistema operativo y sistemas de comunicación permiten, un sistema de cómputo
distribuido. A este compuesto se le suele llamar sistema Cliente/Servidor”[SIN92].
“Básicamente, una arquitectura Cliente/Servidor es un enfoque computacional que
separa procesos sobre plataformas separadas interactuando una con otra que permite
compartir recursos tomando la mejor ventaja de los diferentes dispositivos”[BOC94].
Resumiendo Cliente/Servidor es un modelo de cómputo, para crear sistemas de
información usando diferentes tipos de tecnologías, que permiten la distribución de los
recursos dividiendo las tareas de la aplicación.
9
Cap. 1. Modelo Cliente /Servidor
CLIENTE 1
,/q
SERVIDOR
I
‘7
CLIENTE n
...
CLIENTE 2
CLIENTE 3
1.4. Características generales de ClientelServidor
A continuación se enlistan las características que hacen a la arquitectura
Cliente/Servidor más poderosa que otras.
1.4.1 Mantenibilidad
La descomposición de sistemas monolíticos y rígidos en módulos independientes
facilitan el mantenimiento de las aplicaciones.
1.4.2 Modularidad
La arquitectura Cliente/Servidor es construida por medio de módulos conectables
entre sí. Cada Cliente y Servidor es un módulo, el cual es independiente y puede ser
reemplazado. Nuevas funciones pueden ser agregadas escalando los módulos existentes,
o bien, creando nuevos módulos.
1.4.3 Adaptabilidad
La arquitectura Cliente/Servidor puede distribuir de diferentes formas la lógica de
presentación, procesamiento (lógica del negocio) y datos entre el Cliente y Servidor.
10
Cap. 1. Modelo Cliente /Servidor
La adaptabilidad se refuerza con la capacidad de recursión de la arquitectura
Cliente/Servidor (un Servidor puede convertirse en un Cliente y realizar peticiones). La
recursión permite crear servicios lógicos en donde un proceso es ejecutado por más de un
Servidor, y el acceso a los servicios físicos es realizado de una forma indirecta, lo que
oculta a los usuarios la estructura de la arquitectura, la cual puede ser reconfigurada sin
afectar la imagen que el usuario tiene del sistema.
I
Peticiones
Servicios
Servicio
físico
Servicio
físico
1.4.4 Escalabilidad
Junto con las capacidades de modularidad, uso de estándares y adaptabilidad, la
arquitectura Cliente/Servidor puede ser escalada para abarcar los cambios en las
necesidades del negocio.
I.4.5 Portabilidad
El poder de procesamiento puede encontrarse en diferentes plataformas, desde
computadoras portátiles hasta poderosos mainframes. Construir un ambiente
Cliente/Servidor basado en estándares permite colocar los componentes de una
aplicación en la plataforma de cómputo en donde se obtenga su mayor rendimiento.
11
Cap. 1. Modelo Cliente /Servidor
1.4.6 Estándares/Sistemasabiertos
El uso de estándares crea ambientes heterogéneos en donde existen distintos
protocolos de red, distintas plataformas de hardware, diversas configuraciones de redes y
sistemas operativos.
1.4.7 Autonomía
Los clientes pueden poseer mínimas configuraciones de cómputo como podrían
ser: computadoras sin disco duro o terminales gráficas, o bien, totalmente configuradas
para realizar algún tipo de procesamiento. Con una adecuada configuración, cada Cliente
y Servidor puede trabajar en forma independiente.
1.4.8 Flexibilidad
La arquitectura Cliente/Servidor permite modelar las relaciones más complejas
entre usuarios y equipo de cómputo.
La arquitectura Cliente/Servidor puede reducir el costo de mantenimiento debido a
que las aplicaciones heredan los atributos de la arquitectura sobre la cual está construida.
Por lo que las aplicaciones construidas sobre un ambiente Cliente/Servidor son:
escalables, portables, adaptables, modulares, etc. Estas capacidades facilitan el
mantenimiento de las aplicaciones. También se puede incrementar la productividad del
software, eliminando o minimizando la necesidad del desarrollo de nuevo; esto es debido
a la existencia de librerías compartidas, por lo que al aumentar el número de librerías el
tiempo de construcción de nuevas aplicaciones decrece.
La arquitectura Cliente/Servidor establece una división Óptima de trabajo entre las
aplicaciones Cliente y los Servidores de bases de datos. Las aplicaciones Cliente
interactuan y presentan información a los usuarios. Los Servidores de bases de datos
llevan a cabo la manipulación de los datos a una gran velocidad, protegen la integridad de
los datos. Da el control de los datos bajo ambientes distribuidos al administrador del
Servidor de bases de datos y al usuario final la flexibilidad para el uso de archivos o
herramientas de su elección.
1.5. Comunicación Ciiente/Servidor
Diferentes tipos de comunicación son usados por los sistemas Cliente/Servidor, los
tres más importantes son: Conversacional, Llamada de Procedimientos Remotos (RPC) y
mensajes. SQL es de alto nivel y es usualmente construido sobre uno de los tres
anteriores (frecuentemente sobre RPC) [BOC94].
IS.1 Modelo Conversacional
Un ejemplo del modelo conversacional se encuentra en el APPC de IBM. En SNA,
el término “conversation” se refiere a la comunicación entre procesos durante una sesión.
12
Cap. 1. Modelo Cliente /Servidor
El modelo conversacional es particularmente apropiado para situaciones que
involucran muchas interacciones por transacción entre dos puntos, proporciona un control
estricto para interacciones detalladas. Proporciona e implementa rutinas que permite
ejecuciones traslapadas (overlap).
1.5.2 Modelo de Mensajes
Algunos productos que usan este modelo son Windows de Microsoft, Presentation
Manager y CICS. Con Windows y Presentation Manager los mensajes son usados entre
las interfaces de usuario y procesos Windows. El concepto de mensajes es familiar para
cualquiera que entienda los fundamentos de mensajes electrónicos (e-mail).
Usando mensajes, sí un Cliente requiere datos de un Servidor de base de datos, el
Cliente formatea el requerimiento en un mensaje y a su vez el Servidor proporciona la
respuesta en forma de un mensaje también.
Como lleguen los mensajes, son colocados en una cola; en cuanto se este listo
para procesar un mensaje, este es borrado de la cola. Cuando los mensajes entran a la
cola pueden ser ordenados de una de las tres formas siguientes: FIFO (primero que entra
primero que sale), LIFO (Último que entra primero que sale) o de acuerdo a la prioridad
asignada al mensaje.
Un Cliente puede mandar un mensaje a cualquier número de Servidores. Los
manejadores de colas son necesarios en ambos, tanto el Cliente como el Servidor.
Los mensajes han sido desarrollados por sistemas de procesamiento de
transacciones en línea como IMS y CICS.
1.5.3 RPC's
Con RPC's, el procedimiento o subrutina se localiza sobre otra máquina en la red.
Un RPC permite a un programa o un proceso sobre una computadora ejecutar un proceso
sobre un sistema deferente que se encuentra en otra computadora remota. Los
parámetros que sean necesarios son pasados cuando se llama al procedimiento.
El procedimiento remoto tiene código que entiende que hacer con la llegada de
mensajes, como responder a estos y como obtener los resultados requeridos para la
llamada del procedimiento.
Hay una gran variedad de diferentes implementaciones de RPC's. las
herramientas generalmente proporcionan un lenguaje y un compilador que facilita la
creación de código fuente portable así como un Run-Time. El desarrollador de aplicación
usa el lenguaje proporcionado por la herramienta RPC para crear una especificación
describiendo aspectos de funcionalidad mientras el Run-Time manipula el ambiente
mandando y recibiendo datos a través de la red.
13
Cap. 1. Modelo Cliente /Servidor
1.6. Costos y Beneficios de ClientelServidor
Los costos de la implementación de soluciones Cliente/Servidor no deben
contemplarse sólo en términos absolutos, sino que deben medirse en función del
beneficio que reporten los nuevos desarrollos. Como el precio de las computadoras
personales se han reducido en los Últimos años, con frecuencia se comete el error de
pensar que las soluciones Cliente/Servidor son económicas, o más económicas que las
basadas en mainframes o minicomputadoras.Algunos estudios muestran que el costo del
hardware y software en un periodo de cinco años representa solamente el 20% de los
costos totales y el 80% restante son costos de infraestructura y gastos de explotación.
Algunos de los factores que son necesarios de tomar en cuenta en un ambiente
Cliente/Servidor son:
Aumento de la complejidad debido a la conexión de múltiples sistemas
heterogéneos.
Diversidad de fuentes de datos.
Nuevas plataformas (sistemas operativos) y operaciones.
Inversión inicial en infraestructura.
Formación y creación de especialistas en nuevas herramientas y metodologías.
Arquitecturas de aplicaciones y diseño para un entorno distribuido.
Nuevas guías de procedimientos operativos.
Soporte técnico a los usuarios.
La inversión en un sistema Cliente/Servidor tiene las siguientes ventajas:
1. Utilizar los adelantos en el campo de la computación de una forma más rápida.
Actualmente, las estaciones de trabajo poseen un considerable poder de
cómputo que anteriormente sólo se encontraba en los mainframes o
minicomputadoras.
2. Permitir que el procesamiento resida cerca de la fuente de los datos, por lo que
el tráfico en la red y el tiempo de respuesta pueden ser reducidos
significativamente.
3. Facilitar el uso de interfaces gráficas, las cuales son fáciles de aprender y
permiten el rápido desarrollo de aplicaciones atractivas y funcionales.
4. Permitir la heterogeneidad en software y hardware, diferentes arquitecturas con
distintos sistemas operativos pueden ser utilizados para el procesamiento. Esta
heterogeneidad es lograda a través del uso de estándares.
5. Impulsar la aceptación de sistemas abiertos.
14
Cap. 1. Modelo Cliente /Servidor
1.7 Beneficios de la Arquitectura ClientelServidor
Los beneficios obtenidos por la implementación de un sistema Cliente/Servidor
pueden ubicarse en alguna de las siguientes categorías:
1. Mayor productividad de los usuarios, debido al uso de interfaces gráficas que
permiten accesar e integrar aplicaciones de una forma intuitiva.
2. Incremento en la disponibilidad de software comercial, como procesadores de
texto, hojas de cálculo, etc.
3. Cercanía del usuario a las aplicaciones y los datos que son necesarios para su
actividad, compartiendo servicios.
4. Mayor disponibilidad de herramientas de desarrollo fáciles de usar, reduciendo
con esto la dependencia del departamento de sistemas.
5. Reducción del costo de mantenimiento.
6. Mejoramiento de la utilización de los recursos de cómputo.
7. Incremento de la portabilidad del software.
8. Mejora del incremento de las redes existentes en una empresa.
9. Reducción en el tiempo de desarrollo de las aplicaciones.
1O. Aumento en la productividad de los programadores.
11. Permite a la empresa adaptarse, muy rápidamente, a los cambios en las
políticas internas de la compañía, como a los avances de la tecnología, lo cual
da a la empresa una ventaja competitiva sobre sus contrincantes.
Los beneficios que se derivan de una aplicación Cliente/Servidor dependen, en
gran medida de las necesidades del negocio.
1.8 Desventajas de la Arquitectura ClientelServidor
1. Si el Servidor realiza la mayor parte del procesamiento de las aplicaciones,
éste puede saturarse y provocar cuellos de botella (bottleneck) al aumentar el
número de usuarios.
2. La administración de esta clase de sistemas es más compleja y delicada,
debido a que se trabaja en un ambiente distribuido.
3. La curva de aprendizaje puede llevar demasiado tiempo.
15
Cap. I.Modelo Cliente /Servidor
4. Sin una clara definición de las metas y objetivos del sistema se puede llegar a
incurrir en costos y tiempos que sobrepasen por mucho a los estimados.
5. Las aplicaciones distribuidas, especialmente las diseñadas para un ambiente
cooperativo son más complejas de desarrollar, impiementar y administrar que
los centralizados.
16
Cap. 2 Conceptos Generales de COM y DCOM
2.1 Introducción
La nueva tecnología en la que se basa Windows NT 4.0 y la implementación de
Microsoft de DCOM suponen grandes avances hacia la informática multinivel. Al examinar
arquitecturas multinivel, es importante tratar las ventajas de este método con detalle y,
además, examinar los campos en los que Windows NT y DCOM pueden mejorarse con
herramientas adicionales que les permitan responder a los desafíos del desarrollo en este
entorno.
Borland es capaz de proporcionar un producto que amplia los servicios ofrecidos
por Windows NT 4.0-MIDAS: Multi-tier Distributed Application Services Suite.
Con MIDAS, Borland está proporcionando una serie de servicios de aplicación de
nivel medio que amplían los estándares del sistema operativo. Estos servicios están
diseñados para resolver desafíos de informática distribuida especiales, desde servicios de
directorio diseñados para localizar aplicaciones en la red hasta integración de bases de
datos y proceso de reglas comerciales.
Borland puede proporcionar esta tecnología debido a su tradicional experiencia en
herramientas de desarrollo y modelos de componente y gracias a tecnologías llevadas a
Borland su división Open Environment. El producto Entera del Open Environment Division
proporciona una arquitectura abierta y flexible que durará perfectamente hasta la próxima
década. La infraestructura creada con Entera ofrece un entorno dimensionable para
desarrollar y distribuir aplicaciones de empresa que integran varios GUI y varias fuentes
de datos en un entorno de informática distribuida.
2.2 Creando aplicaciones dimensionables con Windows NT y DCOM
Con el lanzamiento de Windows NT 4.0, Microsoft ha proporcionado un nuevo
conjunto de tecnologías y servicios para que los desarrolladores creen aplicaciones
multinivel, intranet e Internet. Windows NT 4.0 ofrece el núcleo de estas posibilidades
mediante DCOM (Distributed Common Object Model: modelo de objeto común
distribuido).
Como DCOM es una extensión de COM, conviene hablar un poco sobre COM.
Las aplicaciones que funcionan en Windows 95 y Windows NT tienen espacios de
memoria protegidos. Esto asegura que una aplicación no pueda acceder a la memoria
ocupada por otra aplicación. Aunque en general éste es un modelo adecuado, existen
razones para proporcionar un nivel de comunicación entre aplicaciones. Este nivel de
comunicación es proporcionado en Windows 95 y Windows NT mediante COM. COM
ofrece el protocolo que permite a una aplicación interactuar con otra en la misma
máquina. La imagen siguiente representa la arquitectura COM.
17
Cap. 2 Conceptos Generales de COM y DCOM
Arquitectura COM
Ahora que COM ha proporcionado la posibilidad de comunicarse con otra
aplicación que funcione en la misma máquina, el siguiente paso es proporcionar la
capacidad de comunicarse con una aplicación funcionando en una máquina distinta
dentro de la red. Esto es esencialmente lo que ofrece DCOM. La imagen que mostramos
a continuación representa gráficamente la arquitectura DCOM:
Arquitectura DCOM
DCOM ofrece a una organización muchos beneficios que van más allá de
proporcionar simplemente la habilidad de crear aplicaciones en red. La sección siguiente
resalta alguno de los beneficios de DCOM, y continúa con una explicación sobre alguno
de los campos en los que DCOM puede mejorarse con otras herramientas.
18
Cap. 2 Conceptos Generales de COM y DCOM
2.3 Neutralidad de los Lenguajes de Programación
Si una aplicación está escrita con Delphi, puede activarse y utilizarse desde una
aplicación Visual Basic. Esto evita que los desarrolladores se queden bloqueados
utilizando una sola herramienta, lo que les permite seleccionar la herramienta más
adecuada para el trabajo.
2.4 Gestión de la conexión
DCOM utiliza un contador de referencia para determinar cuántos clientes están
conectados a un determinado servidor. Así,cuando un nuevo cliente se añade a la lista, el
contador se incrementa y, a la inversa, cuando un cliente se desconecta del servidor de
aplicaciones, la referencia disminuye. Cuando el contador de referencia llega a cero, la
aplicación se cierra. Cuando un servidor de aplicaciones ya no esté en funcionamiento,
DCOM lanzará la aplicación y establecerá el contador de referencia de la manera más
adecuada.
Si un cliente se desconecta sin que disminuya el contador de referencia, debe
existir un modo de que el servidor disminuya el contador de referencia. Esto se lleva a
cabo enviando el servidor un "ping" al cliente. Si el servidor no logra hacer llegar al cliente
un "ping" tres veces seguidas, la conexión se considerará cerrada y el contador de
referencia será ajustado.
2.5 Interfaces múltiples
DCOM se implementa fundamentalmente mediante la utilización de interfaces. Las
interfaces son los métodos expuestos y las propiedades de un objeto en particular. Puede
haber muchas interfaces para el mismo objeto. Esto ofrece la posibilidad de personalizar
un objeto sin tener necesariamente que volver a desarrollarlo. Esto es especialmente
importante cuando el objeto requiere una funcionalidad adicional que sólo necesitan un
subconjunto de los clientes. En esta situación, el desarrollador puede utilizar la misma
implementación con distintas interfaces. Una interface puede proporcionar la funcionalidad
básica necesaria; el otro puede proporcionar la funcionalidad mejorada. Esto puede
llevarse a cabo incluso aunque la implementación real pueda ser exactamente la misma.
Integración con otros protocolos de red
Como DCOM está basado en sencillos protocolos TCP/IP y RPC, los servidores de
aplicación pueden llamarse desde cualquier punto de Internet utilizando TCP/IP básico u
otros protocolos basados en TCP (como PPTP --Point to Point Tunneling Protocol--) para
usuarios que conectan o HTTP para usuarios de Internet. Soportando el nivel más bajo de
interoperabilidad de red, la comunicación en red de DCOM es transparente para las
aplicaciones. Esto ofrece muchas opciones de red distintas para el desarrollador para que
tome la decisión de elegir la mejor conectividad para la aplicación.
A continuación vamos a ver algunos de los campos de DCOM que podrían
beneficiarse de la incorporación de otras herramientas.
19
Cap. 2 Conceptos Generales de COM y DCOM
2.6 Independencia en la ubicación y equilibrio de carga
Aquí el concepto es que la aplicación cliente no se ocupa de averiguar dónde está
situado el servidor de aplicaciones, sólo de que pueda conectarse a él. Como DCOM está
dirigido hacia aplicaciones conectadas en red, el Único criterio que se puede aplicar es
que la aplicación exista realmente en la red. El modo en que una máquina cliente
"encuentra" a un servidor de aplicaciones es localizando las entradas de registro
adecuadas en el archivo de registro del cliente. Simplemente cambiar la información de
registro del Servidor A al Servidor B hará que el cliente cargue la aplicación en el Servidor
B. Cuando una aplicación tiene muchos usuarios, estos pueden dividirse en grupos de
usuarios. Por ejemplo, el Grupo 1 podría estar utilizando un servidor de aplicaciones de
inventario que está funcionando en el Servidor A mientras que el Grupo 2 puede utilizar la
misma aplicación funcionando en el Servidor B. Haciendo esto, la carga puede
equilibrarse a lo largo de las distintas máquinas.
Este tipo de equilibrio de carga se llama estático, porque los usuarios siempre
conectan con el mismo servidor, sea cual sea el número de usuarios que estén
conectados. Esto está bien para situaciones sencillas, pero la mayoría de las veces la
carga necesita equilibrarse dinámicamente. Teniendo en cuenta el ejemplo de arriba,
añadamos un poco de complejidad más realista. En ciertos momentos del día, el Grupo 1
requiere utilizar mucho más el servidor de aplicaciones. En ese mismo momento, las
necesidades del Grupo 2 son bajas. Si se utiliza equilibrio de cargas estático, el Servidor 1
estará bastante infrautilizado, mientras que el Servidor 2 estará sobrecargado. Si hubiera
una forma de pasar dinámicamente algunos usuarios del Grupo 1 al Servidor 2 en lugar
de al Servidor 1, basándose en el tráfico de red existente para cada servidor, la utilización
global estaría equilibrada en los dos servidores, dando como resultado un mejor
rendim¡ento.
DCOM por sí solo no resuelve equilibrio de carga dinámica. No obstante,
recomienda que los desarrolladores creen un objeto de referencia para ocuparse de este
requisito de aplicación.
Borland ha desarrollado un objeto de referencias de este tipo (la tecnología
Business ObjectBroker en Delphi 3 ClienüServer y MIDAS).
2.7 Seguridad frente a los fallos y tolerancia a los errores
DCOM proporciona soporte básico para la seguridad frente a los errores con las utilidades
de "pinging". Esencialmente, esto significa que si un servidor de aplicaciones falla por
cualquier razón, DCOM intentará reiniciar la aplicación. Aunque ésta es una función
importante, no resuelve momentos en los que el servidor de aplicaciones no puede
reiniciarse debido a diversas razones, incluyendo fallos en la red, fallos de hardware,
fallos en la aplicación, etc.
En la página blanca de Microsoft sobre DCOM, "DCOM Technical Overview", la
solución recomendada a un sistema de aplicaciones realmente tolerante a los fallos se
describe de la siguiente manera:
20
Cap. 2 Conceptos Generales de COM y DCOM
"DCOM facilita la implementación de la tolerancia a los errores. Una técnica es el
componente de referencia introducido en la sección anterior. Cuando los clientes detectan
el fallo de un componente, vuelven a conectar con el mismo componente de referencia
que estableció la primera conexión. El componente de referencia tiene información sobre
los servidores que ya no están disponibles y proporciona automáticamente al cliente una
nueva muestra del componente funcionando en otra máquina".
Aunque DCOM proporciona la infraestructura para crear un sistema así, no se ha
implementado en DCOM propiamente dicho. Con Business ObiectBroker y OLEnterprise,
los usuarios de Delphi 3 ClienüServer y MIDAS tienen un componente de referencia
similar. Este servicio de aplicación funciona tal y como se ha descrito arriba.
2.8 Integración de base de datos
Para comprender las cuestiones sobre integración de bases de datos, podemos
estudiar los fundamentos de DCOM. DCOM se basa en llamadas a procedimiento remoto
(RPC). Hay una limitación en las RPC, como que existe un conjunto limitado de tipos de
datos soportados. Estos tipos de datos son los tipos sencillos (por ejemplo enteros,
cadenas, arrays, binarios, etc.). Lo que no se soporta es la transferencia de tipos de datos
complejos, como los objetos. Aunque los datos de una base de datos suelen entrar en la
categoría de los tipos de datos sencillos, los conjuntos de datos en sí no. Algunos
fabricantes han aprovechado esta cuestión devolviendo conjuntos de tipos de datos
sencillos, un array para cada columna. Aunque esta técnica transporta los datos, la
idoneidad para los datos se pierde en la conversión. Es necesario que exista un
mecanismo que distribuya un conjunto de datos de base de datos ("Data Sets"), permita al
usuario examinar y modificar dicho conjunto de datos y permita al usuario enviar dichas
modificaciones de nuevo al objeto comercial de nivel medio y finalmente a la base de
datos.
Además de devolver los datos de la base de datos, hay también una cuestión
acerca de las reglas comerciales. Una función básica de un servidor de bases de datos es
la integridad y validación de los datos. Si un servidor de aplicación sólo envía los datos
desde la base de datos hasta el cliente, entonces ocurrirá una de dos cosas. Si el
desarrollador no realiza codificación adicional en el cliente para evitar obvias infracciones
de la integridad de los datos, el usuario final sólo estará informado de dicha infracción de
las reglas una vez que hayan enviado los datos de vuelta al servidor de aplicaciones o al
SGBDR. Esto dará como resultado una interface de usuario nada sencillo de manejar y
tráfico de red innecesario. La alternativa es reprogramar las reglas en la parte de cliente
de la aplicación. No obstante, esto tiene otros efectos secundarios. Si la regla cambia, la
parte de cliente debe actualizarse. Aunque esto parezca un paso sencillo, donde hay
muchas aplicaciones cliente distintas que necesitan ser reconstruidas y muchas máquinas
cliente para reinstalar el software, esto es en realidad un proceso complejo y que requiere
bastante tiempo.
21
Cap. 2 Conceptos Generales de COM y DCOM
Ambos temas sobre integración de bases de datos se resuelven utilizando las
tecnologías Remote DataBroker y ConstraintBroker de Borland dentro de Delphi 3
ClientíServer y MIDAS.
2.9 Resumen
La implementación que ha realizado Microsoft de DCOM ha supuesto un gran
avance hacia el esfuerzo de la informática multinivel. No obstante, hay desafíos
adicionales que quedan sin resolver por Windows NT 4.0 y DCOM. Estos campos
incluyen equilibrio de cargas, seguridad frente a los fallos, tolerancia a los errores e
integración de bases de datos. Los productos de Borland Delphi 3 ClienüServer y MIDAS
resuelven estos campos con tecnologías como Business ObjectBroker, Remote
DataBroker y ConstraintBroker.
22
Cap. 3. Comunicación Cliente/Servidor bajo el concepto de COM
3.1 Antecedentes
COM es una forma para que los diferentes componentes de software se puedan
comunicar. Es un estándar binario y de red que permite que dos componentes se
comuniquen sin necesidad de saber sobre qué máquina están corriendo, qué sistema
operativo están usando o en qué lenguaje están escritos. COM proporciona transparencia
de localización (no importa si los componentes son procesos internos DLLs o EXE locales
o componentes localizados en otra máquina. Los componentes principales en una
comunicación por medio de COM son los objetos y las interfaces. A continuación
describiremos cada uno de ellos de una forma técnica
3.2 Objetos
COM está basado en objetos, pero no son precisamente como los que conocemos
de C++ o de Visual Basic. Para nuestros fines que nos interesa aquí un componente y un
objeto es lo mismo, pero se usará el término componente cuando se refiera a la
arquitectura de la aplicación mientras que el término objetos se usará cuando se hable de
la implementación.
Los objetos COM están bien encapsulados. No se puede tener acceso a una
implementación interna del objeto, mucho menos se tiene la forma de conocer las
estructuras de datos que el objeto podría estar utilizando. Los objetos COM se podrían ver
como una caja negra. Todos los detalles de implementación están ocultos.
La única forma de tener acceso a un objeto COM es a través de una interface.
Por ejemplo, un objeto puede tener una interface IFOO. Esta interface es la Única manera
de comunicarse con el objeto.
IFoo
Objeto con interface, aún no es COM
3.3 Interfaces
Las Interfaces son usadas para que se comunique un objeto y un cliente de aquel
objeto y el papel que juega COM en esta comunicación es proporcionar transparencia de
localización.
Cada aplicación tendrá la responsabilidad del manejo de memoria al hacer uso de
COM según el tipo específico de la aplicación.
23
Cap. 3. Comunicación Cliente/Servidor bajo el concepto de COM
Las interfaces son un conjunto de funciones que se pueden llamar para conseguir
que el objeto haga algo. En C++ las interfaces son representadas como una base de
clases abstracta, por ejemplo la interface I F 0 0 podría verse como
class IFoo
virtual void Funcl (void) =O;
virtual void Func2 (int nCount) = O;
1
Nótese que puede haber más de una función en una interface y que todas las
funciones son funciones virtuales puras, es decir que su implementación no está en la
clase IFoo.
Las interfaces son contratos fuertemente tipificados entre un cliente y un objeto
hablando semánticamente, y para COM, es cualquier estructura donde el objeto expone
su funcionalidad a través del mecanismo de interface, que a su vez sigue un estándar
binario que permite que un cliente y un objeto interoperen sin considerar el lenguaje de
programación usado para implementarlos. Cada interface es un contrato inmutable, como
si fuera un grupo funcional que es referido al tiempo de ejecución con un único
identificador de interface global que permite a un cliente preguntar a un objeto si este
soporta una semántica de interface sin necesidad del encabezado y sin problemas de
versiones. El cliente pregunta usando la función Querylnterface de pertenece a la
interface IUnknown la cual es la interface base de todos los objetos. El cliente siempre
tratará con objetos a través de apuntadores de interface y nunca tendrá acceso
directamente al objeto. Una interface no es un objeto, de hecho un objeto puede tener
más de una interface si este tiene más de un grupo de funcionalidad que este soporta.
La interface se puede visualizar como un contrato entre el componente y el cliente.
En otras palabras la interface no sólo define qué funciones están disponibles, sino que
también define qué regresa el objeto cuando las funciones son llamadas. Esta definición
semántica está en términos del comportamiento del objeto. Por esta razón el contrato
tiene que ser documentado fuera del código fuente. Es importante hacerlo notar puesto
que el cliente no tendrá porque tener el código fuente.
Una interface no es un objeto ni mucho menos es una clase de objetos. En C++
se puede instanciar un objeto de una clase, pero un objeto no se puede instadar con un
tipo de interface.
En las aplicaciones de C++ las interfaces están definidas como clases de base
abstracta. Esto es, la interface es un clase de C++ que sólo tiene la definición o
declaración de las funciones miembro, lo que significa que la interface no contiene la
implementación de estas funciones, sino Únicamente prescribe la definición de la función
para algunas otras clases que implementar (los compiladores de C++ generaran errores
cuando se compile el código que intenta instanciar una clase base abstracta). Las
aplicaciones C++ implementan objetos COM heredando estos prototipos de funciones
para una o más interfaces, predominando todas las funciones de la interface
proporcionando una implementación de cada función. Este es como una aplicación COM
en C++ implementa las interfaces de un objeto.
24
Cap. 3. Comunicación Cliente/Servidor bajo el concepto de COM
Un objeto tendrá que implementar cada una de las funciones de las interfaces que
soporte.
En COM se usa la palabra interfaz en un sentido diferente al que usa
típicamente se usa en C++ o en un lenguaje de programación orientada a objetos. En
C++ la interface describe todas las funciones que un objeto soporta y que el cliente de un
objeto puede llamar para interactuar con él. En COM una interface se refiere a un grupo
predefinido de funciones relacionadas que una clase COM implementa pero no
necesariamente representan todas las funciones que una clase soporta. La separación de
la funcionalidad de un objeto del grupo es lo que permite que COM y las aplicaciones
COM eviten problemas de herencia
Una vez que el contrato de interface es publicado contrato es inmutable (ya no hay
forma que pueda cambiar debido a que otros componentes dependen de el)
Pero, ¿que pasa si se olvidó algo, o si los requerimientos cambian?
Una forma par modificar un contrato, es escribir un nuevo contrato. La lista de
interfaces del estándar OLE cuenta con muchas interfaces: IClasssFactory,
IClassFactory2 y así sucesivamente. Para nuestro ejemplo se tendría una interface
llamada I F 0 0 2 y el objeto se vería como:
IF002
IFoo
a
Objeto con 2 interfaces, aún no es COM
Por convención el nombre de una interface comienza con una I
De esta forma concluimos que los objetos pueden soportar múltiples interfaces. De
hecho los objetos COM soportan por lo menos 2 interfaces, la interface IUnknown que se
describirá más adelante y una interface que describa lo que se desee que haga el objeto
y para que un componente soporte una interface, el objeto tiene que implementar cada
uno de los métodos o funciones de las interfaces
Por otro lado, estas interfaces tienen algo en común. ¿se tiene que reescribir toda
la implementación de la nueva interface que tiene casi exactamente lo mismo que la vieja
interface. No, porque COM soporta herencias de interfaces. Mientras no cambien las
funciones que existen en IFoo, podemos definir IF002 como sigue
Class IF002: public IFoo
{//heredando Funcl y Func2
virtual void Func2Ex (double nCount ) = O;
1
Llamando a los métodos definidos en las interfaces
Las llamadas a métodos de objetos COM son simplemente llamadas a funciones
virtuales de C++
25
Cap. 3. Comunicación Cliente/Sewidor bajo el concepto de COM
Supongamos que tenemos una clase de C++ llamada CFoo que implementa la
interface IFoo. Nótese que se hereda de la interface IFoo.
Class CFoo : public IFoo
{
void Funcl ( ) { /* implementación de la función Funcl ...*/ }
void Func2 ( ) { /* implementación de la función Func2 ...*/ }
El apuntador para hacer referencia a una interface será llamado apuntador de
interface. Supóngase que se puede conseguir uno. El código se podría ver como sigue
#include
void DoFoo ( )
IFoo * pfoo = Obtener-Apuntador Para-El-Objeto-Cfoo
( );
/* llamando a los métodos de la interface */
pfoo -> Funcl ();
pfoo -> Func2 ( 5 );
1
Lo que realmente sucede es :
rt. Se hace referencia al apuntador pFoo para buscar el apuntador vtable del
objeto
rt. Se hace referencia al apuntador vtable y se indexa para buscar la dirección del
método que fue llamado.
El siguiente diagrama muestra los pasos descritos:
I
i
i
Objeto al cual
pFoo apunta
n
i
I
-_--------b
i
i
Límite del objeto
cliente
(ai
i
I
CFoo-Fund (
CFoo-FuncE(
int nCount)
{/*...*O
/-J
vtable de
CFoo
!
Llamando a una función vjrtual de C++ a través de un apuntador de inte-rface
Recuerde que para cada funcion virtual en C++, se tienen una vtable (tabla virtual)
que apunta a aquellas funciones. Y que las llamadas son siempre hechas indexando a la
vtable. Nótese que el apuntador es sólo parte del mecanismo del llamado de un objeto
que reside en el módulo cliente, y el resto es implementado por el objeto.
26
Cap. 3. Comunicación ClienteíServidor bajo el concepto de COM
3.4 Identificadores en COM
Antes de seguir adelante, es necesario tener algunos identificadores para referirse
a varias entidades en el mundo COM. Primero es necesario un identificador para el objeto
COM. Segundo, se necesitará un identificador para cada interface. Ahora bien, los
identificadores deben ser Únicos para todas las máquinas, puesto que no hay manera de
saber sobre qué máquina se instalará el componente. En otras palabras estos
identificadores deben ser globalmente Únicos.
Afortunadamente existen algoritmos y formatos de datos que ayudan a crear tales
identificadores. Por ejemplo al usar el número de tarjeta de red de la máquina, junto con la
hora y otro dato daría como resultado un identificador Único global. A este tipo de
identificadores también se les conoce como GUID* y son creados por un programa
llamado GUIDGEN.EXE*. Los GUID's son almacenados en una estructura de 16 bytes
(128 bits) dando 2(Iz8)posibles GUID's.
En C++ hay tipos de datos definidos por archivos de encabezados de COM para
GUID, CLSID * y IDD. Puesto que estas estructuras son muy largas para pasarse por
valor, se hará uso de REFCLSID y REFllD como parámetros para pasar los GUID's. Se
tiene que crear un CLSID por cada objeto que se escriba y un IID por cada interface que
se vaya a crear.
Una clase COM es una implementación particular de cierta interface; la
implementación consiste de una código máquina que se ejecuta cuando se interactua con
una instancia de una clase COM. Un objeto COM está definido por un Único CLSID de
128 bit que asocia una clase objeto a un DLL o EXE en el sistema de archivos
3.5 Interface estándar
Todos los objetos en COM, por medio de una interface, permiten a los clientes
acceder a 2 tipos de operaciones básicas:
0
Navegar entre las múltiples interfaces de un objeto a través de la función
Quervlnterface
0
Controlar el tiempo de vida de los objetos por medio de un mecanismo de
conteo con las funciones AddRef & Release
Estas operaciones constituyen la interface IUnkown de la cual toda interface
hereda.
Con la función Querylnterface es un mecanismo con el cual un cliente puede
obtener un apuntador de interface para un objeto en particular, puede solicitar
apuntadores adicionales de otras interfaces del mismo objeto. Un parámetro de entrada
apara el Querylnterface es el IDD que esta siendo solicitada. Si el objeto no soporta esta
interface, regresa un error.
27
Cap. 3. Comunicación ClienteíServidor bajo el concepto de COM
Querylnterface proporciona una manera robusta y confiable para un componente
para indicar que hechos no soporta un contrato dado.
Existen 4 métodos a traves de los cuales un cliente obtiene su primer apuntador a
interface dado un objeto.
Llamar a las funciones COM que crearan un objeto de un tipo predeterminado que es una función que solo regresará un apuntador a una interface en
específico para un objeto en específico
Llamar a las funciones COM Library API que puede crear un objeto basado
en un identificador de clase y que regresa cualquier apuntador a un tipo de interface
pedida.
0
Llamar a una función miembro de una interface que crea otro objeto y
regresa un apuntador de interface de un objeto separado
0
lmplementar un objeto con una interface a traves de la cual otro objetos pasa
su apuntador de interface al cliente directamente. Este es el caso donde el cliente es
un objeto implementador y pasa un apuntador a su objeto y a otro objeto para
establecer una conexión bidireccional
COM define un gran conjunto de interfaces estándares y sus IID's asociados. Por
ejemplo la madre de todas las interfaces es la ¡Unknown que tiene un IID 'O0... 46', este
está definido por COM y nunca uno se refiere a él directamente, en su lugar se utiliza el
símbolo IID-IUnknown, el cual está definido en los encabezados.
La interface IUnknown tiene 3 funciones
HRESULT Querylnterface (REFIID rid, void ** ppvobject);
ULONG AddRef ( );
ULONG Release ( );
Varios de los programas COM estarán hechos usando interfaces estándares.
Muchos de ellos estarán proporcionando implementaciones para interfaces estándares de
tal forma que otros clientes COM y objetos puedan utilizar el objeto
Existen algunas macros usadas en COM para describir el tipo de dato de retorno y
la convención de llamado de funciones.
Usando estas macros, las declaraciones de arriba se pueden ver como:
STDMETHODIMP Querylnterface (REFIID riid, void ** ppvobject);
STDMETHODlMP-( ULONG) Add Ref ( );
STDMETHODIMP-(ULONG) Release ( );
28
Cap. 3. Comunicación Cliente/Servidor bajo el concepto de COM
3.6 Interfaces Personalizados
Son las interfaces que uno crea. Uno tienen que crear su propio IID para estas
interfaces y definir su propia lista de funciones. En el ejemplo la interface IFoo es una
interface custom. Se ha definido un IID llamado IID-lfoo con el valor de '13C0205C-A7531ldl-A52D-0000F8751 BA7' generado por el GUIDGEN.
Recordemos la declaración de la clase que originalmente se tenía:
class IFoo
{
virtual void Funcl ( void) = O;
virtual void Func2 ( int nCount) =O;
1
Modificaremos esta declaración para ser condescendientes con COM cambiándola
a:
interface IFoo: IUnknown
{
virtual HRESULT STDMETHODCALLTYPE Funcl ( void) = O;
virtual HRESULT STDMETHODCALLTYPE Func2 ( int nCount) =O;
1
Usando las macros descritas arriba, esto se convierte en:
interface IFoo: IUnknown{
STDMETHOD Funcl (void) PURE;
STDMETHOD Func2(int nCount) PURE;
1
STDMETHOD usa STDMETHODCALLTYPE el cual esta definido como -stdcall,
indicando al compilador que debe generar una función estándar, llamando secuencias de
estas funciones. Recuerde que se usaron macros debido a que las definiciones de ellos
cambiaran conforme el código se porte a diferentes plataformas.
Casi todas las funciones COM regresan un código de error en HRESULT. Este
HRESULT es un número de 32-bits, donde el bit de signo se usa para representar éxito o
falla y los restantes 31-bits para indicar la facilidad Ó el código de error.
Hay que hacer notar que se está derivando IFoo de la interface estándar de COM:
IUnknown. Esto significa que cualquier clase que implemente IFoo también necesitará
implementar las 3 funciones AddRef, Release y Querylnterface. También la vtabla de IFoo
tendrá apuntadores a estas 3 funciones antes de los apuntadores a Funcl y Func2. Esto
da un total de 5 funciones en la vtable que se tienen que implementar. Todas las
interfaces son derivadas de IUnknown, así que todas las interfaces COM tienen estas 3
funciones más las funciones adicionales de la interface
29
Cap. 3. Comunicación ClienteíServidor bajo el concepto de COM
3.7 El compilador MIDL
Pero no se tendrá que escribir la declaración de arriba, esto lo generará el
compilador MIDL. Cuando se crea una interface generalmente se utiliza un Leguaje de
Descripción de Interface (IDL), así un compilador de un LDI puede generar encabezados
de archivos para lenguajes de programación de tal forma que las aplicaciones puedan
utilizar esta interface, crear proxy y tuberías de los objetos para proporcionar llamadas de
procedimientos remotos y salidas necesarias para hacer RPC a través de la red.
Recordemos que los objetos COM pueden ser DLL’s para ser usados como procesos
internos, lo que significa que están en el mismo espacio de dirección. Así que si se pasa
un apuntador de algún dato a un servidor que es un proceso interno, el servidor puede
hacer referencia al apuntador directamente.
También un objeto puede ser un servidor local (.EXE), y no es más que un
proceso externo o remoto al que se ejecuta en diferente espacio de direcciones. En
cualquier momento se va a necesitar pasar el apuntador del objeto a los métodos COM,
pero surge el siguiente problema: el apuntador no tiene significado en ningún otro
espacio de direcciones, lo que es significativo son los datos a los que apunta este. Estos
datos tienen que ser copiados en otro espacio de direcciones. A este proceso de copiar
los datos correctos se le llama “marshaling”. COM hace el marshalling en muchos casos,
pero para que esto suceda, se necesita decirle además del tipo de apuntador cómo será
usado el apuntador. Por ejemplo si el apuntador apunta a un arreglo o una cadena, o un
parámetro de entrada solamente. No hay forma de expresar esto en C++.
Por razón es necesario un lenguaje llamado IDL que sirve para definir interfaces.
MIDL.EXE compila el archivo IDL que se escribe para producir varias salidas. Las salidas
serán los archivos que son los encabezados que se incluirán en el código.
El código IDL se ve muy similar al anterior, solo que esta vez no se encuentra la
palabra virtual. Si nosotros creamos una nueva interface IF002 la cual agrega un nuevo
método Func3 a los otros 2 métodos, la definición de la interface se vería como:
[ uuid (13C0205C-A753-11dl-A52D-0000F8751BA7)]
interface IF002 : lunknown
{
HRESULT Funcl ( );
HRESULT Func2 (int in-only);
HRESULT Func3 ([in, out] int v-inout);
1;
Los atributos en un archivo IDL están encerrados por los paréntesis cuadrados ’[ 1’
. Estos siempre aplican a lo que se encuentra inmediatamente después, por ejemplo el
atributo uuid de arriba se aplica a la interface, esto es el IID de la interface (UUID es
sinónimo de GUID). El atributo [in, out] se aplica al apuntdor y le dice a COM que tendrá
que hacer el marshalling un mismo entero tanto como para entrada como para salida
cuando se llame a la función Func3.
30
Cap. 3. Comunicación Cliente/Servidor bajo el concepto de COM
Existe código IDL para definir solamente el objeto. El fragmento de código para
definir nuestro objeto podría verse como
[ uuid (13C0205C-A753-11dl-A52D-0000F8751BA7)]
CoClassFoo
c
1
[default] interface IFoo;
Así es como el CLSID es asociado con la clase y cómo es definido el conjunto de
interfaces que la clase implementa
31
Cap.4. Creación de un objeto COM y uso de sus Interfaces
4.1 Antecedentes
Una vez que el CLSID es asociado con un objeto, se puede crear el objeto, esto es
muy fácil sólo con una llamada a una función.
IFoo * pfoo= null
HRESULT hr =CoCreatelnstances (CLSlD-Foo, NULL, CLSCTX-ALL,
IID-IFoo, (void (**) &pFoo);
Si CoCreatelnstances tiene éxito éste crea una instancia de un objeto identificado
por el GUlD CLSID "CLSID-Foo". Nótese que no hay un apuntador al objeto, en lugar de
esto, siempre se refiere a un objeto a través del apuntador de interface. Por esta razón
se tiene que especificar qué interface se desea (IlD-IFoo) y pasar el apuntador a
CoCreatelnstance para almacenar al apuntador de interface. Los otros dos parámetros no
los discutiremos porque nos son importantes en este momento.
CoCreatelnstance regresa un HRESULT para indicar si tuvo o no éxito. Así que
siempre usaremos una macro SUCEEDED para verificar el resultado. Una vez que el
objeto ha sido creado exitosamente ya se puede utilizar el apuntador de interface para
llamar a los métodos de interfaces como se muestra enseguida
If (SUCCEDED (hr) )
{
pfoo->Funcl ( );
pfoo->FuncZ ( 5 );
pfoo->Release ( ); /* debe liberarse la interface una vez usada */
1
else
/ creación fallada
}
Es importante liberar el apuntador de interface una vez que se haya terminado de
utilizar, llamando a la función Release. Nótese que puesto que todas las interfaces son
derivadas de IUnknown, todas las interfaces soportan Release. El objeto COM es
responsable de liberarse así mismo cuando se le diga que lo haga. Si se hubiese
olvidado llamar a Release, el objeto estaría perdidizo. Este es un problema muy común en
la programación COM. Nótese que solamente se libera la interface si realmente se crea.
32
Cap.4. Creación de un objeto COM y uso de sus Interfaces
El siguiente diagrama muestra al nuevo objeto creado. Por convención, IUnknown
no es etiquetada.
Un objeto COM simple con la interface IUnkown
Ahora que se ha implementado la interface IUnknown, se tiene realmente un
objeto COM.
Si se agrega una interface IF002 al objeto, se tendría un total de 3 interfaces para
un sólo objeto.
IFoo
IF002
0-I
Y
Un objeto COM que soporta varias interfaces
4.2 GUID's y Registro
¿Cómo encontró COM el código del objeto para crearlo? La respuesta es simple,
COM revisó en el registro. Cuando un componente COM es instalado, este tiene que
tener una entrada correspondiente en el registro.
Para nuestra clase Foo, la entrada se podría ver como
HKEY-CLASSES-ROOT
CLSlD [ uuid (13C0205C-A753-11d l -A52D-O000F8751BA7)]= "Foo-Class"
En HKEY-CLASSES-ROOT\ CLSID hay una entrada para el CLSID de nuestra
clase. Así es como CoCreatelnstance busca el nombre del DLL del componente. Cuando
se le proporciona el CLSID a CoCreatelnstance este encuentra el nombre del DLL, lo
carga y crea el componente
Si se conoce el nombre del objeto (ProglD), pero no su CLSID, se puede buscar el
CLSID en el registro
33
Cap.4. Creación de un objeto COM y uso de sus Interfaces
4.3 Módulos componentes de clases e interfaces
Es común que un módulo DLL o EXE implemente más de un componente COM.
Cuando esto suceda, habrá más de una entrada CLSID que se refiera al mismo módulo
Un módulo (la básica unidad que se construye y se instala) puede implementar
uno o más componentes. Cada componente tendrá su propio CLSID y entrada en el
registro que apunte al nombre del archivo del módulo. Cada componente implementa al
menos 2 interfaces : IUnknown y la interface que expondrá la funcionalidad del
componente. Esta se ve como
Módulo 0o.OLL contiene la implementación de tres objetos :
Foo, Goo, F002. Cada objeto implementa la interface Iunknown
y una o más interfaces adicionales
4.4 Obteniendo otra interface con Querylnterface.
Supóngase que se tiene un nuevo y mejorado objeto F 0 0 2 que implementa 2
interfaces customs: IFoo y IF002. Hasta el momento se sabe cómo crear un objeto
usando CoCreatelnstance y cómo obtener el apuntador de una de sus 3 interfaces (IFoo,
IF002, IUnknown)
Pero, ¿cómo se obtiene el apuntador de otra interface del mismo objetos?. No
podemos utilizar CoCreatelnstances otra vez, porque se estaría creando un nuevo objeto.
Esto es un problema que el método Queylnterface de la interface IUnknown resuelve.
Recuérdese que dado que todas las interfaces heredan de IUnknown, todas tienen que
implementar el método Querylnterface. Se usa el primer apuntador de interface para
llamar al método Querylnterface para obtener el segundo apuntador de interface.
34
Cap.4. Creación de un objeto COM y uso de sus Interfaces
IFoo *pfoo= NULL;
HRESULT hr =CoCreatelnstances (CLSlD-Foo2, NULL, CLSCTX-ALL,
IID-IFoo, (void (**) &pFoo);
if (SUCCEEDED ( h r )
{
pFoo->Funcl ( );
IF002 * pF002 = NULL;
hr = pF002 ->Querylnterface (IID-IFoo2, void (**) &pF002);
if (SUCCEEDED ( hr )
{
int inoutval =5;
pFoo2->Func3 (&inoutval);
pF002-> Release ( );
1
1
pFoo->Release ( );
Nótese que se le pasa a Querylnterface el IID de la interface que se desea y el
apuntador donde almacenará el nuevo apuntador de la interface. Una vez que
Querylnterface regresa el valor de retorno exitoso, ya se puede utilizar el apuntador de
interface para llamar las funciones de interface. Hay que hacer notar que hay que liberar
los 2 apuntadores una vez que ya se utilizaron
4.5 Controlando el ciclo de vida del objeto
Es responsabilidad del cliente liberar un objeto cuando este objeto ya no esta
siendo usado. En un sistema de orientación a objetos el cliente puede hacer esto
diciéndole al objeto que se destruya. La dificultad yace en tener que hacer que el objeto
sepa cuando este tiene que salvarse para destruirse. Los objetos COM, los cuales son
dinámicamente asignados, deben permitirle al cliente decidir cuando el objeto ya no está
en uso, ya sean objetos locales o remotos que pueden estar en uso por múltiples clientes
al mismo tiempo, el objeto debe esperar hasta que todos los clientes hayan terminado de
usarlo antes de liberarse.
COM especifica un mecanismo de conteo de referencia para proporcionar este
control. Cada objeto contiene un conteo de referencia de 32-bits que mantiene al tanto de
cuantos clientes están conectados a él, esto es, cuántos apuntadores existen a cualquiera
de sus interfaces de cualquier cliente.
AddRef incrementa el conteo y Release lo decrementa. Cuando el conteo llega a
cero, la función Release está autorizada a liberar el objeto.
35
Cap.4. Creación de un objeto COM y uso de sus Interfaces
Cada vez que un cliente llama a una función que regresa un nuevo apuntador de
interface como lo es Querylnteface, la función que ha sido llamada es responsable de
incrementar la referencia a través del apuntador de regreso
Una instancia de una implementación de interface es simplemente un apuntador a
un arreglo de apuntadores a funciones. En realidad un apuntador a una interface es
realmente una apuntador a apuntador de una tabla de apuntadores de función.
Objetos con múltiples interfaces son capaces de proporcionar mas de una tabla de
función
4.6 Interfaces que permiten interoperabilidad
Existen 3 propiedades de interfaces para proporcionar estos
Polimorfsmo (habilidad de asumir varias formas).- En programación 0.0.describe
la habilidad de tener un solo enunciado que invoque a diferentes funciones a diferentes
tiempos. Todas las interfaces COM son polimorficas cuando tú llamas a una función
usando un apuntador de interface sin especificar que implementación es llamada.
Dado que la interface sigue un estándar binario, el cliente sabe cómo usar una
interface dada para interactuar con cualquier objetos que soporte esta interface sin
preocuparse de cómo el objeto implementa el contrato (interface). Esto permite la
interoperabilidad cuando escribes una aplicación que puede cooperar con una aplicación
sin saber de antemano quien o qué son ellas.
Encapsulación si se tiene implementada una interface, se puede cambiar o
actualizar la implementación sin afectar a cualquiera de los clientes de tu clase.
Similarmente tu permaneces inmune cuando otros hacen cambios a su implementación
La interface ¡Unknown tiene otras 2 funciones: AddRef y Release.
La mayoría de los objetos COM mantienen un conteo de referencia. Cuando esta
referencia llega a cero, el objeto se libera implícitamente. Cuando se usa Release se
libera el apuntador de interface y el objeto se libera a sí mismo en el momento apropiado.
AddRef incrementa el conteo de referencia y Release lo decrementa
Pero en el ejemplo que hemos estado usando ¿porqué si no se usó AddRef sí se
uso Release?
Bueno, esto se debe a que cuando se llama a CoCreateInstances, esta función
llama a Querylnterface, el cual a su vez llama a AddRef. Uno está obligado a llamar a
Release con el mismo apuntador de la interface
Se necesita llamar AddRef si se está haciendo una copia del apuntador de
interface para que el conteo de referencia de la interface sea el apropiado.
36
Cap.4. Creación de un objeto COM y uso de sus Interfaces
¿Qué sucede cuando se llama a CoCreatelnstances?
Cuando se llama a CoCreatelnstances, COM busca el registro para encontrar el
CLSID, y este a su vez ayuda a encontrar el archivo DLL Ó EXE que implementa al
objeto, Pero no se ha explicado de los detalles de cómo esto sucede. CoCreatelnstances
encapsula la siguiente funcionalidad:
IClassFactory *pCF;
CoGetClassObject (rclsid, dwClsContext, NULL, IID-IClassFactory,
(void **) &pCF);
Hresult = pCF ->Createlnstance(pUnkOuter,riid, ppvobj);
pCF->Release ( );
Como se puede ver, existen 3 pasos. El primer paso es obtener la clase del
objeto vía el identificador de interface IID-IClassFactory, después de llama a la función
Createlnstance de la interface IClass-Factory de la clase del objeto (los parámetros de
este llamado son los pasados en la llamada de CoCreatelnstances. Por ahora se tiene
una instancia de nuestro objeto en *ppvObj. Finalmente se libera la clase del objeto.
4.7 Clase objeto
La clase objeto es un objeto especial de COM cuyo principal propósito es
implementar la interface IClassFactory. Este objeto es especial porque no es creado por
CoCreatelnstance como muchos de los objetos COM. Este es creado llamando a
CoGetClassObject y además no se preocupa por el tipo de objeto creado, (no le importa si
es un servidor in-process o local). La clase objeto maneja todos estas diferencias. Sin
embargo, CoGetClassFactory, necesita hacer una búsqueda en el registro para resolver
cómo crear o encontrar una clase objeto para el CLSID pedido
La clase objeto es un ejemplo del poder de polimorfismo. Se puede llamar a COM
API para obtener el objeto y una vez que lo hemos obtenido se puede determinar que este
soporte la interface estándar que se necesite (IclassFactory) y poder llamar los métodos
de esta interface en este caso, la función sería Createlnstances. Si esto tiene éxito,
regresará un apuntador de interface que se refiere a aquella clase.
Cada clase objeto está asociado con un CLSlDen particular. Nótese que
1ClassFactory::Createlnstance no tiene a CLSID como parámetro, la clase objeto sabe
qué CLSID es, para crearlo. Esto significa que para cada CLSID separado que se tenga,
se tiene al menos una clase objeto disponible a crear
Además IClassFactory, la clase objeto puede implementar las interfaces que se
desee. Por ejemplo se podría definir una interface que permita que ponga los valores por
defaults para las instancias de objetos creados de una clase objeto en particular. Nótese
que no se garantizó que haya una sola clase objeto para un CLSID dado, así que
CoCreateClass se puede encontrar más de una vez.
37
Cap.4. Creación de un objeto COM y uso de sus Interfaces
¿Porqué hay una clase objeto?
La razón más importante para requerir la implementación de una clase objeto
COM es que COM puede tener una manera polimórfica estándar de crear cualquier tipo
de objeto sin pedir que el cliente sepa exactamente los detalles de creación. La clase
objeto encapsula este conocimiento. Esto implica que la clase objeto y el objeto real
tienen una relación muy cerrada y por lo regular un conocimiento uno del otro.
Pero, ¿porqué no tener un esquema más simple?. Por ejemplo tener una función
llamada Createlnstance DLL que podría aceptar un CLSID y crear una nueva instancia.
Una función tal como esta es más simple que un objeto COM y una IClassFactory
La respuesta es que ésta no trabajaría para los EXE’s
No solo no se podría exportar funciones de los EXE’s sino que tampoco se podría
trabajar bien con objetos remotos. De esta forma cuando se hace de una, una clase
objeto, un objeto COM, este toma precauciones de todas las cuestiones de inprocess/outof process
Puesto que la clase objeto es un objeto que sabe hacer las cosas bien, crea una
instancia del objeto etiquetado. Nótese que una vez que la clase objeto es creada COM
queda fuera del cuadro en términos de la creación de instancias. Así que para el primer
objeto de un tipo determinado, COM tiene que hacer mucho trabajo. Primero tiene que
buscar el CLSID en la lista de clases objeto registrados en el registro si la clase objeto no
existe. Si la clase objeto registrado es creado, COM lo crea tal vez incluyendo un DLL o
comenzar un EXE. Finalmente COM llama a la IclassFactory::Createlnstance de la
correcta clase objeto para crear la instancia.
Finalmente, la clase objeto puede soportar maneras adicionales para crear
objetos. Tal como la interface IclassFactoriy2 que es usada en lugar de IClassFactory
para crear controles con licencia. Estos tipos de controles necesitan que el usuario tenga
derecho sobre el control que quiere crear.
4.8 lmplementado la clase objetos.
Este es un ejemplo muy sencillo de un objeto COM Esto significa que al menos se
tiene que implementar la interface IUnknown. Muchos de los objetos también implementan
la interface Iclassfactory que permite la creación de instancias.
38
Cap.4. Creación de un objeto COM y uso de sus Interfaces
Se puede tener una clase objeto declarada como sigue:
Class CmyClass0bject:public IClassFactory
{
protected: ULONG m-cRef;
public: MyClassObject ( ) : mcRef(0) { };
//funciones miembro de la interfaz Unknown
STDMETHODIMP Querylnterface (REFIID, void ** );
STDMETHODIMP-ULOG AddRef (void);
STDMETHODlMP-U LOG Release (void);
//funciones miembro de la interfaz IclassFactory
STDMETHODIMP Createlnstnacie(1Unknown*, REFllD iid, void **)
STDMETHODlMP Lockserver(BOOL);
Hay varias maneras de crear una clase objeto, ninguna de las cuales implica a
CoCreatelnstnaces. Basta con declarar en el código la siguiente línea:
CMyClassObject g-cfMyClassObject;
Esto significa que el objeto siempre existirá cuando el archivo DLL sea cargado.
4.9 lmplementando los métodos de la clase objeto
IUnknown ::AddRef y IUnknown:: Release.
La clase objeto es global. Este siempre existe y puede ser destruida con solo
descargar el archivo DLL. Puesto que nunca se borra este objeto y puesto que las
referencias a la clase objetos no mantiene a un servidor cargado, casi no se utiliza la
implementación del conteo de referencias. Sin embargo se puede manejar este conteo de
referencias.
Si el objeto fue crea dinámicamente, Release podría tener la responsabilidad de
liberar al objeto cuando el conteo de referenica llegue a cero. Esto se puede ver como
sigue:
STDMETHODIMP -(ULONG) cmYcLASSoBJECT:: aDDrEF ()
{
return lnterlockedlncrement (&m-cRef);
1
STDMETHODIMP -(ULONG) CmyClassObject :: AddRef ( )
1
return InterlockedDecrement(&mcRef);
39
Cap.4. Creación de un objeto COM y uso de sus Interfaces
La función Querylnterface de la interface IUnknown.
La implementación de Querylnterface de este objeto especial es 100 % estándar
debido a que es una clase objeto.
STDMETHODIMP CMyClass0bject::Querylnterface(REFIID riid,
void *** ppv)
{
*ppv = NULL;
if (rid == IID-IUnknown 11 riid == IID-IclassFactory )
{
*ppv =static-cast4classFactory *>this;
(static-cast4classFactorry *> *ppv )) ->AddRef () ;
return S O K ;
1
1
else return E-NOINTERFACE;
La función Createlnstance de la interface IclassFactory puede verse como:
STDMETHODIMP CMyClass0bject::Querylnterface(IUnknown * pUnkOut,
REFllD iid, void * ppv)
{
*ppv = NULL;
if (punkouter != NULL)
return CLASS-E-NOAGGREGATION ;
//Creación del objeto
CMyObject * pObj = new cMyObject ();
if (pObj == NULL)
return E-OUTOFM EM0RY;
/Obtiene el primer apuntador de interface el cual hace un AddRef
HRESULT hr = pOvj ->Querylnterface (iid, ppv);
//Borra un objeto si la interfaz no esta disponible
//Supone que el conteo de referencias estaba en cero
if (FAILED ( hr )
delete pObj;
return pObj;
40
Cap.4. Creación de un objeto COM y uso de sus Interfaces
Primero que nada, si el apuntador es no null, se crea el objeto debido a que se
está preguntado si soporta una agregación. Después asignamos al objeto y se regresa un
E-OUTMEMORY si no se puede asignar el objeto a memoria. Después se llama a la
función Querylnterface del objeto recientemente creado y regresa un error si no tuvo éxito,
de lo contrario regresaría un valor de éxito.
Hay diferentes patrones de haces la inicialización de la función Querylnterface del
objeto dependiendo de cómo el objeto en si haga su referencia inicial .
La función Lockserver de la interface Iclassfactory.
Lockserver principalmente incremente y decrementa el seguro y el objeto global .
este no intenta liberar el archivo DLL cuando el conteo llega a cero (Si el objeto es un
servidor .EXE, el servidor podría darse de baja cuando el conteo de referneica llegase a
cero previniendo que no hubiese usuarios interactuando con él)
STDMETHODIMP CMyClass0bjetc::LockServer (BOOL flock)
{
if ( fLock )
Interlockedlncrement (&g-cObjectsAndLocks);
else
InterlockedIncrement (&g-cO bjectsAndLocks);
return hr;
1
41
Cap. 5 Implementación del Objeto
5.1 lmplementando el propio objeto
Se ha mostrado la clase objeto que implementa a IclassFactory, esta se puede
llamar por medio del método Createlnstance. La forma de hacerlo es por medio de la
función new:
CMyObject *pObj = new CMyObjectO;
Ahora veamos lo que éste objeto hace Ó como se crea.
5.2 El diseño de CmyObject
Este objeto implementa cuatro interfaces: IFoo, IF002, lgoo y lunknown(Aunque
lunknown se puede considerar como parte de todos los objetos).
IF002 es una extensión de IFoo (IFoo mas una nueva función), mientras que IGoo
es una interface totalmente separada. Así el diagrama de CMyObject se puede ver de la
siguiente forma:
moo
moa 2
IGOO
El
Figura I.
CMyObject, la cual soporta cuatro interfaces.
La interface Ifoo, mostrada anteriormente es:
interface IFoo : IUnknown {
STDMETHOD Funcl (void) PURE;
STDMETHOD Func2(int nCount) PURE;
1;
Ahora se usará el IDL para definir las interfaces. Así, el IDL para la interface anterior es:
uuid(7BA998DO-C34F-I1D I-A54D-O000F8751BA7)
1
interface IFoo : IUnknown
{ HRESULT Funcl ();
HRESULT Func2([in] int inonly);
1;
42
Cap. 5 Implementación del Objeto
La segunda interface, interface independiente, IGoo, se ve de la siguiente forma:
[
uuid(OE02BI34-C350-11d l -A54D-O000F8751BA7),
1
interface IGoo : IUnknown
{
HRESULT Gunc();
1;
La interface rara es IF002, simplemente porque es una extensión de IFoo.
~~id(62F890DA-C361-11
d l -A54D-O000F8751BA7)
1
interface IF002 : IFoo
{
HRESULT Func3([out, retval] int *pout);
1;
Cabe hacer notar que IF002 comprende seis métodos: los tres métodos de
IUnknown, los dos métodos de IFoo y Func3. (Por la misma razón, IFoo y IGoo
comprenden cinco y cuatro métodos respectivamente)
Descripción de lo que hace cada uno de estos métodos:
Cuando un objeto es creado, este tendrá un valor interno de 5. Funcl
incrementará el valor interno y emitirá un sonido si el nuevo valor es un multiplo de 3.
Func2 colocará el valor interno al parámetro que se le pase.
Por medio de la interface iFoo3, que es derivada de IF002, se obtiene el valor
interno actual. En Visual Basic, esta función es llamada de esta forma:
"Text2 = Foo2.Func3" en vez de "Foo2.Func3(Text2)".
La interface IGoo es independiente de el valor interno(no así con IFoo é IF002), lo
que significa que cualquier objeto puede implementar IGoo sin ninguna de las interfaces
IFoo y viceversa. En otras palabras, estas interfaces no estan ligadas.
5.3 lmplementando interfaces multiples usando herencia multiple
El objeto implementa 4 interfaces: IFoo, IF002, IGoo y IUnknown. Ahora, siempre y
cuando la implementación de Querylnteríace regrese un puntero válido para cada una de
estas interfaces, no importa que tan preciso sea nuestro código. Por ejemplo, si se
escriben objetos COM en C, se crearía un arreglo de puntero a funciones y
Querylnterface regresaría la dirección de un puntero que apunta a vtable. Esto es algo
complicado, por lo que no se recomienda usar C para hacer objetos COM.
43
Cap. 5 Implementación del Objeto
En C++ existen también una variedad de métodos, uno de estos es tener cada una
de las interfaces implementadas por un objeto separado, entonces Querylnterface regresa
un puntero para cada objeto. El método mas claro es heredar de cada una de las
interfaces el objeto. ATL usa este metodo, y el código siguiente también lo hace. Todo lo
que tiene que hacer Querylnterface es regresar el puntero asignarlo a la clase apropiada.
La declaración de la implementación de la clase se ve:
class CMyObject :
public IF002,
public IGoo
{
private:
int m-ilnternalValue;
ULONG m-refCnt;
public:
CMyObjectO;
virtual -CMyObject();
/ I IUnknown
STDMETHODIMP Querylnterface(REFIID, void **);
STDMETHODIMP-(ULONG) AddRef(void);
STDMETHODIMP-(ULONG) Release(void);
/ I IFoo
STDMETHODIMP Funcl ();
STDMETHODIMP Func2((/*[in]*/ int inonly);
/ I IF002
STDMETHODIMP Func3(/*[out, retval]*l int *pout);
I/ IGoo
STDMETHODIMP Gunc();
1;
Cabe hacer notar que no se hereda explicitamente de Unknown ó IFoo. De la
misma manera, no se hereda de IUnknown porque tanto IF002 como IGoo
heredan(directamente Ó indirectamente) de IUnknown.
Si se hereda directamente de IFoo Ó IUnknown, se crearán ambiguedades, por lo
que habrá un error de compilación. Así que la regla es: heredar solo de las clases
derivadas. Si alguna otra clase que el objeto implementa hereda de una clase base, se
esta también implementando, por lo que no se debe heredar de clases base. De hecho se
tienen que implementar todos los métodos.
44
Cap. 5 Implementación del Objeto
Diagrama de herencia del objeto:
Figura 2. La herencia del objeto.
Cabe hacer notar que hay dos caminos de herencia para IUnknown. Si se
heredara la implementación de IUnknown, sería un verdadero problema porque
tendriamos dos implementaciones de IUnknown para el mismo objeto. Lo mismo sucede
con las demás interfaces. Pero IUnknown no tiene ni datos ni funciones, así que solo se
heredaría la interface.
Cuando se hereda solo la interface para una clase, normalmente se escribe solo
una implementación para esas funciones, tipicamente en las clases derivadas. Así solo se
escribirá una implementación de Querylnterface, AddRef y Release, y esto estará en
CMyObject.
Todos los punteros de la vtable de IUnknown apuntaran a la misma
Querylnterface, AddRef y Release funciones. Esto es consistente con el comportamiento
de las funciones virtuales de C++: cuando se llama a una función virtual, siempre se llama
a la implementación disponible derivada. Así la vtable par CMyObject puede verse como
sigue:
45
Cap. 5 Implementación del Objeto
Castto
IUnknovin,
IFoo,
IFoo2, or
CMipbjeci
I
1
(
L
( uI-
F-
II
{
IFm2 IFm
C@Objeci:; Queryinterface
CW#ject::A ddRef
I
m@bj=t
Castto
lGoo
Figura 3. Una posible implementación de una vtable para CMyObject.
Cabe hacer notar que los punteros de vtable pointers, aún los de sección de
IUnknown de IGoo, apuntan a las funciones de CmyObject
Así se puede ver que una implementación de Querylnterface, AddRef y Release
satisface todas las interfaces de donde se ha heredado. Esto es muy manejable para
IUnknown, pero no es correcto para interfaces no relacionadas. Si se esta implementando
un objeto COM con herencia multiple, el método que se escriba será llamado por ambas
interfaces. Este es le mayor problema para la implementación de objetos COM, aunque
normalmete esto no aparece tan seguido, y cuando aparesca se puede resolver el
problema implementando una de las interfaces usando una clase anidada, mientras se
usa herencia multiple para el resto de los objetos.
Se muestra un diagrama del objeto CMyObject:
this
staiic-cast4Goo *>(this)
FL
\table pir for all but Goo
r
L
itable pir for lGoo
I
m JlntemalVBlue
I
Figure 4. Un objeto CMyObject.
46
Cap. 5 Implementación del Objeto
5.4 lmplementandoa Querylnterface
Ya que se sabe que es lo que hace Querylnterface por que lo hace se presenta el
código:
STDMETHODIMP CMyObject::Querylnterface(REFllD
iid, void **ppv)
{
*ppv = NULL;
if (iid == IID-IUnknown
¡id == IlD-IFoo 11
¡id == IID-IFoo2)
11
{
*ppv = static-cast4Foo2 *>(this);
1
else if (¡id == IID-IGoo)
*ppv = static-cast4Goo *>(this);
1
if (*PPV) {
AddRef();
return S O K ;
1
else return E-NOINTERFACE;
1
Se llama AddRef se hay éxito en Querylnterface - cuando se da un puntero a una
interface, se debe usar AddRef para direccionarlo y el cliente debe liberarlo con con
Release cuando este hecho.
Cabe hacer notar que cuando el cliente el cliente requiere a IID-IGoo, se esta
llamando a AddRef con un puntero diferente del que se regresa al cliente. Con el
propósito de dar soporte por interface, los clientes de COM deben de llamar a AddRef y
liberar con Release sobre el puntero de interface correcto.
5.5 lmplementando a AddRef y Release
La implementación de estas es muy sencilla:
STDMETHODIMP-(ULONG) CMyObject::AddRef(void)
{
return ++m-refCnt; // NOT thread-safe
1
47
Cap. 5 Implementación del Objeto
STDMETHODIMP-(ULONG) CMyObject:: Release(void)
{
--m-refCnt; // NOT thread-safe
if (m-refCnt == O) {
delete this;
return O; // can't return member of deleted object
1
else return m-refcnt;
1
Si se esta soportando operaciones de multihilos, se tiene que usar
Interlockedlncrement y InterlockedDecrement. Solo usando los operadores de incremento
y decremento es mas eficiente(ATL hace la mas eficiente elección posible
automáticamente cuando se le dice que modelo de hilos se va a usar)
Release tiene la responsabilidad de destruir el objeto cuando la referencia sea
cero, y cuando esto pasa, este debe de regresar cero para indicar que el objeto ya no
existe.
5.6 El constructor y destructor
Código para el constructor y destructor:
CMyObject::CMyObject() : m_ilnternalValue(5), m-refCnt(1)
{
g-cObjectsAndLocks++; // NOT thread-safe
1
CMy0bject::-CMyObjectO
{
g-cObjectsAndLocks--; // NOT thread-safe
1
Como es de esperarse, el constructor inicializa el valor interno de las variables
miembro, en este caso se coloca m-ilnternalvalue a cinco.
48
Cap. 5 Implementación del Objeto
Además, el constructor y destructor tienen dos pequeños trucos. Primero, el
constructor inicializa el objeto con un contador de referencias(n0 cero). Paraesto se
considera en CMyClassObject::Createlnstance,la cual llama a Release sobre el objeto,
para despues hacer el primer Querylnterface. Si el primer Querylnterface tiene exito, este
llama a AddRef, la cual incrementa el contador. Si este falla, AddRef no es llamado, así la
referenciaso se mantiene. En cualquier caso, Createlnstance llama a Release, la cual
decrementa el contador. Si el primer Querylnterface tiene éxito previamente, el contador
es entonces uno; Si este falla, el contador se pone en cero y Release borra el objeto.
Implementación de 1ClassFactory::Createlnstance:
STDMETHODIMP CMyClassObject::Createlnstance(lUnknown
*punkouter,
REFllD iid, void **ppv)
{
*ppv=NULL;
if (punkouter != NULL) //just say no to aggregation
return CLASS-E-N OAGGREGAT1ON;
//Create the object
CMyObject *pObj = new CMyObjectO;
if (pObj == NULL)
return E-OUTOFMEMORY;
//Obtain the first interface pointer (which does an AddRef)
HRESULT hr = pObj->Querylnterface(iid, ppv);
// Delete object if interface not available
// assume initial ref count was one, not zero
pObj->Release(); // back to one if QI OK, deletes if not
return hr;
1
El segundo truco es que el constructor y el destructor incrementan y decrementan
los objetos globales y el contador de seguridad. Este contador es inicializado con cero
cuando el DLL es cargado e incrementado para cada objeto creado(except0 la clase
objeto) y cuando es llamada la IClassFactory::LockServer(TRUE).
Este es decrementado
cuando cada objeto es destruido y cuando es llamado LockServer(FALSE). Es mejor
incrementar en el constructor y decrementar en el destructor. Por supuesto que es posible
incrementar en Createlnstance y decrementar si se borra el objeto en Release, pero esto
no es muy elegante
49
Cap. 5 Implementación del Objeto
Para un servidor en proeceso, este contador es solo usado por la función global
DIICanUnloadNow:
STDAPI DIICanUnloadNow() {
if (gcObjectsAndLocks == O)
return S-OK;
else
return S-FALSE;
1
5.7 lmplementando una interface propia
Ahora que ya se tienen todos las cosas que necesita COM para funcionar, se
pueden implementar métodos propios:
STDMETHODIMP CMyObject::Funcl ()
{
m-ilnternalValue++;
if (m-ilnternalValue % 3 == O) MessageBeep((U1NT)-I);
return S-OK;
1
STDMETHODIMP CMyObject::Func2(/* [in] */ int inonly)
c
m-ilnternalValue = inonly;
return S-OK;
1
I/ IF002
STDMETHODIMP CMyObject::Func3(/* [out, retval] */ int * pout)
{
MeccageBeep((U1NT)-l);
*pout = m-ilnternalvalue;
return S-OK;
1
50
Cap. 5 Implementación del Objeto
I/ IGoo
STDMETHODIMP CMyObject::Gunc()
{
MessageBeep((UINT)-l);
return S-OK;
1
5.8 Contruyendolo
Como se ve es muy sencillo construir la aplicación. Para este objeto ejemplo, the
only other files you have to write is the IDL file and the linker .DEF file.
Ya se ha escrito la mayoria del archivo IDL durante el presente documento, pero
se necesita algo mas de código al principio:
import "oaidl.idl";
import "ocidl.idl";
And some code to the end, after the interface definitions:
[
uuid(7BA998C3-C34F-I1D I -A54D-O000F8751BA7)
1
library NONATLOBJECTLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
[
uuid(2E98593E-C34A-I1D I -A54D-O000F8751BA7)
1
coclass MyObject
[default] interface IFoo;
interface IF002;
interface IGoo;
51
Cap. 5 Implementación del Objeto
El primer GUlD (empieza con 7BA9) es la GUlD para la biblioteca de tipos; la
segunda (empieza con 2E98) es el CLSID para este objeto.
Cabe hacer notar que no se creó el archivo cabecera para las interfaces. MlDL
cuidara de esto tecleando en la linea de comando:
midl /Oicf /h "NonATL0bject.h" /¡id "NonATLObject-i.c"
"NonATLObject.idl"
MlDL creará algunos archivos utiles: una biblioteca de tipos NonATLObject.TLB,
la cual el cliente usa, el archivo proxy/stub, un archivo cabecera NonATLObject.h, and un
archivo que contiene el código necesario para definir el GUIDs (IIDs y CLSID),
NonATLObject-i. c.
Después se incluye NonATL0bject.h en todos los archivos *.CPP antes de incluir
la cabecera. Esta cabecera incluye automaticamente todas las ventanas y cabeceras
COM que se necesitaran. Haciendo esto(inc1uir antes que la cabecera), se elimina la
necesidad de incluirla en la cabecera.
También se necesita incluir NonATLObject-i.c en solamente uno de los archivos
*.CPP. Esta contiene la definición de todos los GUIDs. Lo anterior dicho se ve de la
siguiente forma:
#include "NonATLObject.h"
#include "Myobject. h"
#include "NonATLObject-i .c"
// The global class object
CMyClassObject g-cfMyClassObject;
// Count of locks and objects
ULONG gcObjectsAndLocks = O;
// Class members and DII* functions next
Finalmente, se definen las funciones
DIIGetClassObject y DIICanUnloadNow.
miembro
para
ambas
clases
Una vez que se ha construido el servidor, se registra este como ya se
describió,sustituyendo el correcto GUlD
52
Cap. 5 Implementación del Objeto
5.9 El objeto clase y la fabrica de clases
).Que pasa cuando se llama a Createlnstance?
Se ha dicho que cuando se llama a CoCreatelnstance, COM busca el registro del
CLSID, ya sea por medio de un DLL o un EXE que implementan el objeto. Los detalles
de cómo sucede este, se mostraran enseguida
CoCreatelnstance encapsula las siguientes funcionalidades
IClassFactory *pCF;
CoGetClassObject(rclsid, dwCIsContext, NULL,
IID-IClassFactory, (void **)&pCF);
riid, ppvobj)
hresult = pCF->Createlnstance(pUnkOuter,
pCF->Release();
Como se puede ver, hay tres pasos. El primer paso es obtener el objeto clase por
medio
de
su
interface
IID-IClassFactory.
Después,
se
llama
a
1ClassFactory::Createlnstancesobre este objeto clase(Los parámetros para esta llamada
son pasados por la llamada de CoCreatelnstance). El parámetro punkouter es usado
para reusar un método llamado agregación. Así ahora se tiene un puntero a una instancia
del objeto en *ppvObj. Finalmente, se libera el objeto clase.
5.9.1
El objeto clase
El objeto clase es un objeto COM especial cuyo propósito principal es
implementar la interface IclassFactory, aunque aveces se oirá que este objeto hace
referencia a una fabrica de clases Ó aún a la fabrica de objetos clase, pero es más exacto
llamarlo como el objeto clase.
Este objeto es especial porque no es creado al llamar a CoCreatelnstance o
IClassFactory::Createlnstance,
como sucede con la mayoria de los objetos COM. En vez
de esto, este siempre es creado al llamar a CoGetClassObject.
El objeto clase es un grandioso ejemplo de polimorfismo. Se puede llamar a COM
API con el fin de obtener el objeto, pero una vez que se haya obtenido este objeto, se
puede determinar que este soporta la interface estándar que se necesita IClassFactory y
se puede entonces llamar los métodos de la interface, en este caso a
1ClassFactory::Createlnstance. Nótese que no se tiene idea de cómo trabaja
Createlnstance. Todo lo que se sabe es que si esta tiene éxito, esta regresará un puntero
de interface que apunta hacia el objeto. Es la identidad del objeto clase la que determina
la conducta exacta.
53
Cap. 5 Implementación del Objeto
Cada instancia del objeto clase esta asociada con un exclusivo CLSID, nótese
que 1ClassFactory::Createlnstanceno tiene un CLSID como uno de sus parámetros. En
vez de esto, el objeto clase sabe a que referenciar. Esto significa que será necesario al
menos un objeto clase para cada CLSID separado que se quiera poder crear.
Resumiendo a IClassFactory, el objeto clase puede implementar cualquier
interface que este quiera. Por ejemplo, se puede definir una interface que permita colocar
defaults para instancias de objetos creados desde un objeto clase particular. Pero nótese
que no se esta asegurando que exista solo un objeto clase para un CLSID dado, así que
si se llama a CoGetClassObject mas de una vez, se puede obtener punteros de interface
a diferentes objetos clase. Y como se puede controlar la creación de objetos clase, se
puede definir esto en la implementación.
5.9.2
Porque existe un objeto clase
Como ya se ha mostrado, la más importante razón para COM en requerir la
implementación de un objeto clase es que COM puede tener una forma polimórfica
estándar de crear objetos de cualquier tipo sin requerir que el cliente conozca los detalles
completos de la creación.
¿Pero porque no un esquema mas simple?, por ejemplo, se puede imaginar una
función en un COM DLL llamada DLLCreatelnstance que aceptara un CLSID y creara
una nueva instancia. Una función como esta es ciertamente más simple que un objeto
COM y IClassFactory.
Pero esto no funcionaría para EXEs. No solo se exportarían funciones desde los
EXEs y esto ciertamente no funcionaría bien para objetos remotos. Así que cuando se
hace el objeto clase a un objeto COM, COM cuida los detalles.
El objeto clase es un objeto COM que sabe como hacer las cosas bien para crear
una instancia del objeto principal, nótese que una vez que el objeto clase es creado,
COM no participa en lo que respecta a la creación de instancias. Así que para un primer
objeto de un particular tipo que es creado, COM tiene que hacer bastante trabajo, tiene
que buscar el CLSID en la lista de objetos clase registrados(0 en los registros si es que el
objeto clase no existe). Si el objeto clase necesita ser creado, COM lo crea. Finalmente,
COM llama a IClassFactory::Createlnstancesobre el objeto clase correcto para crear la
instancia.
Pero si se conserva el objeto clase fuera, se puede evitar la mayoria del trabajo de
las siguientes instancias: simplemente llamando a IC1assFactory::Createlnstancepara
hacer objetos adicionales. Esto puede ser tan rápido como llamar al operador new
directamente, y mucho mas rápido que dejar que COM genere los objetos. Importante: Si
se conserva un objeto clase fuera, se debe de llamar a 1ClassFactory::LockServerpara
informarle a COM que mantenga el servidor en memoria. La referencia al objeto clase no
54
Cap. 5 Implementación del Objeto
conservará el servidor automáticamente en memoria. Este comportamiento es una
excepción al comportamiento normal de COM. SI se falla al accesar al servidor, se puede
causar una violación de protección si se intenta accesar el objeto clase después de que
el servidor fue descargado. Finalmente, el objeto clase puede soportar formas adicionales
de crear objetos, como es la interface IClassFactory2, interface que es usada en vez de
IClassFactory para crear controles patentados. Los controles patentados son controles
que requieren que el usuario tenga la licencia correcta de ID antes de que el control
pueda ser creado.
5.9.3
Otra forma de crear objetos y cuando usarla
Si se esta creando solo una instancia de un objeto y se puede usar a
IClassFactory para crear el objeto, se puede usar también a CoCreatelnstance (0
CoCreatelnstanceEx, que puede crear objetos remotos). Pero si se esta creando mas de
una instancia de un objeto, Ó se necesita usar una interface además de IClassFactory
para crear el objeto, se necesita obtener y tal vez mantener un objeto clase.
Obtener el objeto clase es fácil; solo hay que hacer lo que CoCreatelnstance
hace: llamar a CoGetClassObject. Una vez que se tiene el puntero de interface para el
objeto clase, llamar a IClassFactory::LockServer(TRUE)para cargar el servidor en
memoria. Así se podrá llamar a IClassFactory::Createlnstancecuando se necesite una
nueva instancia. Finalmente, cuando los objetos ya fueron creados, hay que liberar el
puntero de interface por medio de la llamada a la función Release y liberar al servidor
por medio de la función IClassFactory::LockServer(FALSE).
5.9.4
lmplementando el objeto clase
Como el objeto clase es un simple objeto COM, este implementa al menos una
interface: IUnknown. Casi todos los objetos clase también implementan a IclassFactory,
así que estos pueden crear instancias:
class CMyClassObject : public IClassFactory
{
protected:
ULONG m-cRef;
public:
CMyClassObject() : mcRef(0) { };
//IUnknown members
HRESULT Querylnterface(REFIID, void **);
ULONG Add Ref(void);
ULONG Release(void);
55
Cap. 5 Implementación del Objeto
//IClassFactory members
HRESULT Createlnstance(1Unknown*, REFllD iid, void **ppv);
HRESULT LockServer(BO0L);
1;
Por supuesto que esta clase contiene declaraciones para cada función en
IClassFactory: Createlnstance y Lockserver. Además de que existen las funciones de
IUnknown. Cabe recordar que IClassFactory es derivada de lunknown.
5.9.5
Como es creado este objeto clase
Hay una variedad de formas de crear un objeto clase, ninguna de las cuales
involucra a CoCreatelnstance. Como solo se necesita una instancia de este objeto y como
este es un objeto pequeño sin constructor, se puede declarar solo un objeto global:
CMyClassObject g-cfMyClassObject;
Esto significa que este objeto siempre existirá cuando el DLL sea cargado.
Con la finalidad de implementar IClassFactory::LockServer,se necesitará también
un contador global de todos las instancias que no sean instancias de un objeto clase y el
número de veces que Lockserver fue llamado:
LONG g-cObjectsAndLocks = O;
5.9.6
Como CoGetClassObject obtiene el objeto clase
COM llama a una función llamada DIIGetClassObject en el DLL. Se debe de
exportar esta función si el DLL contiene COM-creable objetos COM. DllGetClassObject
tiene el siguiente prototipo:
STDAPI DIIGetClassObject(const CLSID &rclsid, const IID &rid,
void ** ppv);
COM pasa como parámetros un CLSID y un IID; DllGetClassObject regresa un
puntero a la interface pedida en *ppv. Si el objeto clase no puede ser creado ó la
interface pedida no existe, es regresado un error en valor de regreso HRESULT (nótese
que STDAPI esta definido para regresar un HRESULT).
Para servidores EXE, el proceso es diferente: Se debe registrar un objeto calse
para cada clase, COM puede crearlas llamando a CoRegisterClassObject para cada
objeto clase. Esto coloca el objeto clase en la lista de objetos clase registrados. Cuando el
proceso EXE termina, este llama a RevokeClassObject una vez por objeto clase para
remover el objeto de la lista.
56
Cap. 5 Implementación del Objeto
Nótese que el cómo COM obtiene el objeto clase, depende de si el objeto es
implementado por un DLL Ó por un EXE. Si es un DLL, este carga el DLL y llama a
DIIGetClassObject. Para un EXE, este carga el EXE y espera hasta que el EXE registre el
objeto clase que esta buscando.
La DIIGetClassObject puede verse de la siguiente forma:
HRESULT DIIGetClassObject(REFCLSlDclsid, REFllD iid, void **ppv) {
if (clsid != CLSID-Myobject) // right CLSID?
return E-FAIL;
// get the interface from the global object
HRESULT hr = g-cfMyClassObject.Querylnterface(iid,ppv);
if (FAILED(hr))
*ppv = NULL;
return hr;
1
Se debe de checar que se pueda ver el CLSID solicitado. Si no, se regresará un
E-FAIL. Después, se llama a Querylnterface para verificar la interface solicitada. Si esta
falla, se debe de poner el puntero de salida en NULL y regresar a E-NOINTERFACE. Si
esta tiene éxito, se regresa S-OK y el puntero de interface.
5.9.7 lmplementando los métodos del objeto clase
5.9.7.1 1Unknown::AddRef y 1Unknown::Release
Se tiene un objeto global, este siempre existe y no puede ser destruido(mientras el
DLL no sea descargado). Como no se borrará nunca este objeto y como las referencias a
los objetos clase no mantienen un servidor cargado, casi no se necesita implementar un
contador de referencias. Sin embargo, COM espera que Release regrese cero cuando
este en un estado liberado, así que se necesita una mínima implementación del contador
de referencias.
AddRef y Release son responsables de mantener el contador de referencias en el
objeto. Nótese que se tiene una variable de instancia m c R e f inicializada a cero. AddRef y
Release solo incrementaran y decrementaran el contador de referencias y regresaran el
nuevo valor de este.
57
Cap. 5 Implementación del Objeto
Si el objeto es creado dinámicamente, seria responsabilidad de Release de borrar
el objeto cuando el contador de referencias llegue a cero.
ULONG CMyClassObject::AddRef() {
return lnterlockedlncrement(&m_cRef);
1
ULONG CMyClassObject::Release() {
return InterlockedDecrement(&m-cRef);
1
En este código se utiliza las funciones de incremento y decremento thread-safe en
vez de usar ++m-cRef y --mcRef para entrar en el hábito de usar Ó pensar en
operaciones multihilos.
5.9.7.2 1Unknown::Querylnterface
La implementación de Querylnterface es 100% estándar para este objeto; no se
necesita nada especial solo por ser un objeto clase. Todo lo que se hace es ver si la
interface solicitada es una de las dos interfaces solicitadas (IUnknown y IClassFactory)
que se soportan, Si sucede esto, se regresa un puntero de interface, con un cast
apropiado; y se llama a AddRef con el puntero al contador de referencias. Si no, se
regresa un código de error, E-NOINTERFACE.
HRESULT CMyClassObject::Querylnterface(REFIID¡id, void ** ppv) {
*ppv = NULL;
if (¡id == IID-IUnknown==iid 11 ¡id == IlD-IClassFactory) {
*ppv = static-cast4ClassFactory *>this;
(static-castclClassFactory *>*ppv)->AddRef();
return S-OK;
else {
*ppv = NULL; // COM Spec requires NULL if failure
return E-NO1 NTERFACE;
1
1
58
Cap. 5 Implementación del Objeto
5.9.7.3 1ClassFactory::Createlnstance
Este es el corazón del objeto clase; la función que crea instancias.
HRESULT CMyClassObject::Create1nstance (IUnknown *punkOuter,
REFllD ¡id, void ** ppv)
*ppv=NULL;
if (punkouter != NULL) //just say no to aggregation
return CLASS-E-NOAGGREGATION;
//Create the object
CMyClassObject *pObj = new CMyObjectO;
if (pObj == NULL)
return EOUTOFMEMORY;
//Obtain the first interface pointer (which does an AddRef)
HRESULT hr = pObj->Querylnterface(iid, ppv);
// Delete object if interface not available
if (FA1LED(hr))
delete pObj;
return hr;
1
Primero, no se soporta agregación, por lo que si el puntero no es NULL, se puede
crear el objeto porque se esta siendo solicitado para soportar agregación. Después, se
autoriza el objeto y se regresa un E-OUTOFMEMORY si no se puede.
Después, se llama a Querylnterface con el nuevo objeto creado para obtener un
puntero de interface para regresar. Si esto falla, se borra el objeto y se regresa un código
de error. Si esto tiene éxito, se regresa código de Querylnterface. Nótese que
Querylnterface llamará a AddRef si tiene éxito, regresando un contador de referencias
correcto para el objeto.
59
~
Cap. 5 Implementación del Objeto
Nótese también que no se incrementó ni el contador del objeto y de lock,
gcObjectsAndLocks. Se pudo haber hecho esto si la creación hubiese tenido éxito, pero
tendríamos que decrementarlo tanto en el Release del objeto Ó en su destructor.
5.9.7.4 IClassFactory::LockServer
Lockserver incrementa y decrementa el contador del objeto y lock. Este no intenta
liberar el DLL cuando el contador llega a cero. (Si este fuera un servidor EXE, el servidor
sería apagado cuando el contador llegara a cero.)
HRESULT CMyClassObject::LockServer(BOOLflock) {
if (fLock)
InterlockedIncrement(&gcObjectsAnd Locks);
else
lnterlockedDecrement(&g-CObjectsAndLockc);
return NOERROR;
1
5.9.7.5 DllCanUnloadNow
COM llamará a DllCanUnloadNow para decidir si descarga ó no un DLL. Se
regresa simplemente un S-OK si hay que descargarlo, S-FALSE si no.
HRESULT DIICanUnloadNow() {
if (gcObjectsAndLocks == O)
return S-OK;
else
return S-FALSE;
1
5.9.8
Usando el objeto desde Visual Basic
Primero, tenemos que agregar una referencia hacia el objeto en el project de visual basic,
esto se hace por medio del submenú de References... que se encuentra en le menú
Projects.
60
Cap. 5 Implementación del Objeto
Después se diseña una forma con un botón para llamar a cada método y un
campo de texto para mostrar el valor actual.
Finalmente, se escribe el código necesario para accesar el objeto. Primero, en la
sección de declaraciones generales se declara una referencia una referencia al objeto:
61
Cap. 5 Implementación del Objeto
Private obj As MyObject
Luego se crea el objeto actual en el método Load para la forma:
Private Sub Form-Load()
Set obj = New MyObject
End Sub
Esto causa que Visual Basic llame a I CoCreatelnstance para crear el objeto.
Ahora que el objeto ha sido creado, se agrega un manejador para llamar los
métodos Funcl y Func2 de la interface por default IFoo:
Private Sub Funcl IncBeep3_Click()
Obj.Func1
End Sub
Private Sub Func2Set-Click()
If IsNumeric(Text1) Then obj.Func2 (Textl)
End Sub
Para llamar métodos de otras interfaces, se tiene que obtener acceso a la
interface. Esto se hace creando una variable del tipo autorizado para la interface, y luego
colocarla apuntando al objeto (Cuando se hace esto, Visual Basic llama a Querylnterface
sobre el objeto). Para cambiar interfaces se hace de la siguiente forma:
Dim F002 As IF002 ' switch interfaces
Set F002 = obj
Después se puede llama a los métodos de IF002 usando la referencia de objeto
F002.
Sabiendo esto, se puede entender el código el código para accesar los otros
métodos del objeto.
Private Sub Func3BeepGet-Click()
Dim F002 As IF002 switch interfaces
Set F002 = obj
Textl = Foo2.Func3
End Sub
I
62
Cap. 5 Implementación del Objeto
Private Sub GuncBeep-Click()
Dim Goo As IGoo switch interfaces
Set Goo = obj
Goo.Gunc
End Sub
Finalmente, se agrega un manejador para el método "Increment Text Box":
Private Sub IncTextBox-Click()
If IsNumeric(Text1) Then Textl = Textl + 1
End Sub
Si se es usuario del enlace tardío(late binding), se debe considerar esto: se puede
usar enlace tardio para accesar el objeto, pero pero solo se podría accesar la interface
por default(1Foo). Enlace tardío no funciona bien para objetos que utilizan múltiples
interfaces, además que tiene un lento funcionamiento.
5.9.9
Usando el objeto desde Visual J++
Es casi tan sencillo como usarlo desde Visual C++ Ó Visual Basic. Primero, se
debe de crear un archivo de clase especial(*.class) que represente el objeto COM. Esto
se hace por medio del wizard de la librería de tipos de Java(Java Type Library Wizard)
que se encuentra en menú Tools del Visual Studio.
MSNBC News Browser Type Library 2 3
UNameOCX OLE Control module
OPlDFetch 1 O Type Library
port2 1 O Type Library
63
Cap. 5 Implementación del Objeto
Esto crea un archivo de clase que es creado en el directorio trustlib (en el mismo
subdirectorio de las demás clases de Java. La ventana resultante tiene la sentencia de
import que se debe de copiar y pegar en el archivo *.java. Esta también tiene una
referencia hacia el archivo summary.txt que contiene una representación textual de la
librería de clases. No compilar este archivo; con esto el archivo *.class ha sido creado.
En este caso la sentencia import tiene "import nonatlobject.*;". Se debe de insertar
esto en la cabecera del archivo *.Java.
Una vez hecho esto, se puede crear y usar el objeto.
El objeto se crea por medio de una simple llamada a la función new:
IFoo myObj = new Myobject();
Nótese que se creo al objeto MyObject, pero se asigno a la referencia de objeto
IFoo. No se puede usar el objeto como un MyObject en Visual J++- Este no reconocería
ó soportaría el concepto de una interface por default.
En este punto, se puede llamar a los métodos de Ifoo:
myObj.Func2(5);
myObj.Funcl();
myObj.Func1();
myObj.Funcl();
// sets
// increments and beeps
// increments
// increments
Si se desea llamar a los métodos de IF002 o IGoo, se tiene que crear una nueva
referencia a objeto y asignar el objeto a los métodos:
IF002 myFoo2 = (IFoo2)myObj;
System.out.println("Value is + myFoo2.Func3() + (8?)");
'I
I'
IGoo myGoo = (IGoo)myFoo2;
myGoo.Gunc(); // beeps
64
Cap. 6 Ambiente Cliente/Servidor bajo COM
6.1 Antecedentes
El Cliente es cualquier pedazo de código que de alguna manera obtiene un
apuntador a través del cual puede tener acceso a los servicios de un objeto y luego invoca
estos servicios cuando sea necesario. El Servidor es cualquier pedazo de código que
implementa el objeto y estructuras de tal forma que la Librería COM pueda hacer
corresponder esta implementación con el identificador de clase. La participación de un
identificador de clase es lo que diferencia un Servidor de un implementador más general
de objetos.
La librería COM utiliza el CLSID para proporcionar el servicio de la implementación
a clientes. El Cliente sólo necesita decirle a COM el CLSID que desea y el tipo de
Servidor, COM localiza la implementación de la clase y estableces una conexión entre
esta y el Cliente
6.2 Clientes y Servidores COM
Cuando una aplicación pasa un CLSID a COM y pregunta por un objeto
instanciado es un Cliente COM. Un Cliente COM siempre pide a COM instanciar objetos
de la misma forma. El método más simple para crear un objeto es con la función COM
CoCreatelnstances. Este crea un objeto de un CLSID dado y regresa un apuntador a
interface de cualquier tipo que el Cliente pide.
Existen 2 tipos de servidores objetos
0
0
DLL En este caso el Servidor es implementado en un modulo que puede ser cargado y
que se ejecutará dentro del espació de direcciones del Cliente
EXE El Servidor es implementado como un modulo ejecutable aparte
Puesto que COM contempla objetos distribuidos, esto también contempla 2 tipos
básicos de servidores para implementar con máquinas remotas. Para permitir que las
aplicaciones Cliente activen objetos remotos COM define el Manejo de Control de Servicio
(SCM)
Un Servidor tiene la responsabilidad de implementar la fabrica de clases, de
implementar la clases de objetos que la fabrica manufacturará, exponiendo la fabrica de
clases a COM y proporcionar el descargamiento del Servidor bajo condiciones correctas.
Para que el Servidor logre estos requerimientos, depende si el Servidor está
implementado como un DLL o un EXE
65
Cap. 6 Ambiente ClienteíServidor bajo COM
6.3 La Librería COM y el Manejo de Control de Servicio
La Biblioteca de COM es una implementación estándar de las funciones API
definas en COM para soportar la comunicación entre objetos y clientes. La biblioteca
COM es la que hace que todo trabaje transparentemente a través de RPC. Si COM
determinar que se tiene que establecer una comunicación entre un Cliente y un Servidor
(local o remoto), este crea un objeto proxy que actúa como un objeto in-process para el
Cliente. Estos proxies hablan con los objetos stubs que están en el mismo proceso como
un Servidor y pueden llamar al Servidor directamente. Los stubs recogen las llamadas
RPC de los proxy y las convierten en llamadas de funciones para el objeto real, luego
pasan los valores de regreso a los proxy vía RPC, los cuales se los entregan al Cliente.
El mecanismo RPC esta basado en el mecanismo estándar DCE de llamadas de
procedimientos remotos.
6.4 Arquitectura para objetos distribuidos
Una arquitectura COM para la objetos distribuidos es similar a la arquitectura
remota, Cuando un Cliente desea conectarse a un objeto del Servidor, el nombre del
Servidor es almacenado en el registro del sistema. Con objetos distribuidos, el Servidor
puede ser implementado como un objetos in-proces .DLL o un modulo local ejecutable o
como un modo ejecutable remoto o un DLL corriendo remotamente. EL SCM tiene la
responsabilidad de localizar al Servidor y correrlo
Hacer una llamada a un método de interface en un objeto remoto implica la
cooperación de varios componentes. La interface proxy es un pedazo de código
específico de interface que reside en espacio de los procesos del Cliente y prepara los
parámetros para transmisión. Este los ordena para que ellos puedan ser reconstruidos y
entendidos en el procesos que los recibe. También la interface de los stub es un pedazo
de código que reside en el espacio del proceso y hace el trabajo inverso al del proxy. El
stub desempaca o desenvuelve los parámetros enviados y los manda hacia el Servidor.
También empaqueta la información de contestación para enviarlos de regreso al Cliente.
La transmisión real de los datos a través de la red es manejado por las librerías de
RPC a tiempo de ejecución y por el canal, parte de la librerías de COM. El canal trabaja
transparentemente con diferentes tipos de canales y soporta tanto aplicaciones de un sólo
hilo o multi-hilos
Este asegura que cuando una petición del Cliente es hecha, el Servidor apropiado
este conectado y listo para recibir tal petición. SCM mantiene una base de datos de
información de clases basadas en e registro del sistema que el Cliente.
Cuando un Cliente hace una petición para crear un objeto de la clase CLSID; la
biblioteca COM contacta al local SCM y pide que el Servidor apropiado sea localizado o
lanzado y se regresa la fábrica de clases a la librería COM. Después de eso, la librería
COM o el Cliente pueden pedir a la fábrica de clases crear un objeto.
66
Cap. 6 Ambiente Cliente/Servidor bajo COM
La acción tomada del SCM depende del tipo del Servidor de los objetos que está
registrado en el CLSDI.
En proceso. El SCM regresa la ruta del archivo DLL que contiene la implementación
del Servidor de objetos. La librería COM carga el DLL y pregunta por el apuntador de
interface de la fábrica de objetos.
Si es local, el SCM ejecuta el Servidor local el cual registra un fábrica de clases en
marcha. El apuntador está disponible a COM.
Si es remoto. El SCM local contacta al SCM que corre en la computadora remota y
remite la petición al SCM remoto. EL SCM remoto lanza al Servidor el cual registra
una fabrica de clase como un Servidor local con COM en la máquina remota. EL SMC
remoto mantiene una conexión de la fábrica de clases y regresa una conexión RPC al
SCM local, el cual corresponde a la fábrica de clases remota. El SCM local regresa la
conexión a COM el cual crea una fabrica de clases proxy el cual internamente remitirá
peticiones al SCM remoto vía la conexión RPC.
6.5 Objetos Conectables y Eventos
En el contexto de la relación Cliente-objeto(Servidor), se supone que el objeto
escucha lo que el Cliente tiene que decir. En otras partes las interfaces entrantes y sus
funciones miembros reciben las entradas de afuera. COM también define mecanismos
donde los objetos puedan soportar interfaces de salidas. Las interfaces de salida
permiten que los objetos tienen 2 formas de conversación con los clientes. Cuando 1
Cliente soporta una o más interface de salida, se dice que es un objeto conectable. Uno
de los muchos usos de las interfaces de salida es la notificación de eventos.
Un objeto conectable, también se le conoce como una fuente. Cada interface está
compuesta de distintas funciones miembros, y cada función representa un evento, una
notificación o una petición. Los eventos y la notificación son conceptos equivalentes y
términos intercambiables ya que ambos son usados para decirle al Cliente que algo
interesante sucedió en el objeto. Los eventos y notificaciones difieren de una petición en
que el objeto espera una respuesta del Cliente. Una petición, por otro lado, es como un
objeto solicita al Cliente una pregunta y espera una respuesta.
En todos los caso, debe haber algún Cliente escuche lo que el objeto tiene que
decir y usa la información sabiamente. Lo que realmente implementa estas interfaces son
llamados sinks. El sink es lo que el Cliente del objeto usa para escuchar lo del objeto.
La solución del problema de integración es un nivel de indirección: un sistema de
archivos dentro de un archivo. En lugar de requerir que una larga secuencia contigua de
bytes en el disco sean manipulados por un sólo archivo manejador con un sólo apuntador
de búsqueda, COM define como tratar un Único sistema de archivos como una colección
estructurada de 2 tipos de objetos (almacenajes) que actúan como directorios y archivos
respectivamente
67
Cap. 6 Ambiente Cliente/Servidor bajo COM
Dentro de la definición de almacenaje persistente de COM hay 2 tipos de
elementos de almacenamiento: los objetos de almacenamiento y los objetos flujos, estos
objetos son objetos generalmente implementados por las Librería COM por sí misma, las
aplicaciones rara vez necesitan implementarlos por sí misma. Estos objetos al igual que
otros en COM, implementan interfaces IStream para objetos de flujo y Istorage para
objetos de almacenamiento.
Un objeto de flujo es conceptualmente equivalente a un archivo de disco. El flujo
es el componente básico del sistema de archivos en el cual los datos viven y cada flujo
por sí mismo tiene derechos de acceso y un Único apuntador de búsqueda. Por medio de
la interface IStream, el flujo puede ser mandado a leer, escribir, buscar o ejecutar unas
cuantas operaciones de sobre sus datos. Los flujos osn nombrados al usar una cadena de
texto y puede contener cualquier estructura interna que se desee debido a que ellos son
simplemente un flujo plano de bytes.
Un objeto de almacenamiento es conceptualmente equivalente a un directorio.
Cada almacenamiento, al igual que un directorio puede contener cualquier número de
sub-almacenamiento (sub-directorios) y cualquier número de flujos(archivos).Además
cada almacenamiento tiene sus propios derechos de accesos. La interface Istorage
describe las capacidades del objeto de almacenamiento tal como enumerar los elementos
(dir), mover, copiar, renombrar, crear, destruir, etc. Un objeto de almacenamiento no
puede almacenar datos definidos por una aplicación excepto que implícitamente
almacene los nombres de los elementos (almacenamientos y flujos) contenidos dentro de
él.
Los objetos de almacenamientos y flujos son compatibles entre procesos. Este es
una característica clave que habilita objetos que corren en in-process ó out-of-process.
Puesto que COM esta cargado en cada proceso separadamente, este debe de usar algún
sistema operativo que soporte mecanismo de memoria compartida para comunicar entre
procesos de elementos abiertos y sus modos de accesos.
Todo objeto de almacenamiento y flujo es un archivo estructurado tiene un nombre
de carácter en específico para identificarlo. Estos nombres son usados para decirle a
Istorage qué elementos en el almacenamiento para abrir, destruir, mover, copiar,
renombrar, etc. Dependiendo del componente, Cliente u objeto realmente define y
almacena estos nombres, convenciones diferentes y poner restricciones.
Los nombres de los elementos contenidos en los objetos de almacenamiento son
manejados por la implementación del objeto de almacenamiento en cuestión. Todas las
implementaciones de objetos de almacenamientos deben por lo menos soportar nombres
de 32 caracteres de longitud, algunas irnplementaciones podrían escoger la longitud de
los nombres.
68
Cap. 6 Ambiente Cliente/Servidor bajo COM
Los nombres de los elementos dentro de un objeto de almacenamiento debe
cumplir ciertas convenciones:
0
0
no pueden contener / \ , : Ó !
. & .. están reservados
Los elementos de almacenamiento y flujo soportan 2 modos de acceso: directo y
transaccional. Los cambios son hechos inmediatamente y permanentemente en modo
directo, mientras que en modo transaccional los cambios permanecen en buffers de tal
forma que ellos podrían ser salvados (comit) o revertidos cuando las modificaciones se
acompleten.
Por naturaleza, el almacenamiento estructurado de COM separa las aplicaciones
de la composición de información dentro de un archivo dado. Todo elemento de
información de este archivo tiene acceso de usar funciones e interfaces implementadas
por COM. Debido a que la implementación es central, un archivo generado por alguna
aplicación usando esta estructura, puede ser visto por cualquier otra pieza de código, tal
como un sistema shell. En otras palabras, cualquier pedazo de código en el sistema
puede usar COM para ver la jerarquía total de los elementos dentro de un archivo
estructurado simplemente navegando con la interface Istorage el cual proporciona
servicios de directorio. Si un pedazo de código también sabe que formato y significado de
un flujo en específico que tiene un cierto nombre, este podría abrir el flujo y hacer uso de
la información de él, sin tener que correr la aplicación que escribió al archivo.
Este es una poderosa herramienta de consulta que ayuda a los usuarios a buscar
información en sus computadoras o aun en la red. Para que esto realmente suceda se
requiere estandarizar ciertos nombres de flujos y el formato de aquellos flujos tal forma
que el shell del sistema pueda abrir los flujos y ejecutar consultas de esta información
Dado que COM permite que un objeto se lea y se escriba para almacenarse, debe
haber una manera en la cual el Cliente le dice al Cliente qué hacer. Esta forma es una
interface adicional que forma un contrato de almacenamiento entre el Cliente y los
objetos. Cuando un Cliente desea consulta al objeto para una de las interfaces
persistentes relacionadas. Las interfaces que los objetos pueden implementar, es
cualquier combinación, son:
Persitstorage. El objeto puede leer y escribir su estado persistente para un objeto de
almacenamiento. El Cliente proporciona el objeto con un apuntador Istorage por medio
de esta interface. Esta es la interface IPersist que incluye una semántica para accesos
de incremento
69
Cap. 6 Ambiente Cliente/Servidor bajo COM
El objeto IPersistStream puede leer y escribir su estado persistente a un archivo en es1
sistema directamente Esta interface no implica Istorage o el lstream a menos que el
archivo accese por medio de estas interfaces, pero el IPersistFile no tiene semántica
relacionada con tales estructuras. El Cliente simplemente proporciona al objeto de un
archivo nombre y ordenes para salvar o cargar, el objeto lo hace si es necesario para
llenar el requisito.
Un moniker es simplemente un objeto que soporta una interface lmoniker
(IPersistStream). La forma persistente de un moniker incluye los datos comprimiendo su
nombre y el CLSID de su implementación la cual es usada durante el cargado del
proceso. Esto permite que nuevos tipos de moniker puede ser creados trasparentemente
para el Cliente.
La función de enlace lmoniker toma como parámetro al identificador de interface
por el cual el Cliente desea hablar al límite del objeto, corre cualquier algoritmo que sea
necesario par localizar al objeto, regresa un apuntador del tipo de interface al Cliente. El
Cliente también pide enlazarse al almacenamiento del objeto
6.6 Transferencia de Datos Uniforme
COM proporciona interfaces para intercambio de datos entre aplicaciones. Esta
tecnología es la Transferencia de Datos Uniforme, el cual proporciona la funcionalidad
para representar la transferencia de datos a través de un sola implementación de un
objeto de datos. Los objetos de datos implementan una interface llamada IDataObject la
cual abarca las operaciones estándares de obtenerlponer datos y consultar/enumerar
formatos así como las funciones por medio de las cuales un Cliente de un objeto de datos
puede establecer una notificación de loop para detectar cambios de datos en el objeto.
Además esta tecnología habilita el uso de más ricas descripciones para los formatos de
datos y el uso de cualquier almacenamiento virtual
La interface IDataObject separa todas las operaciones comunes de intercambio de
lo que es llamada un protocolo de transferencia. Con Uniform Transferencia de Datos,
todos los protocolos están relacionado con intercambio de un apuntador a la interface
IDataObject El Servidor solamente implementa un objeto de datos el cual es utilizable en
cualquier protocolo de intercambio y esto es todo. El Cliente necesita implementar un
pedazo de código para pedir datos del objeto de datos una vez que este recibe un
apuntador a la interface IDataObject de cualquier protocolo. Una vez que el apuntador de
intercambio ha ocurrido, ambos lados tratan de intercambiar datos en un moda por medio
del IDataObject.
70
Cap. 6 Ambiente Cliente/Servidor bajo COM
Esta uniformidad no solamente reduce el código necesario para generar o
consumir datos, sino que también simplifica el código necesario para trabajar con el
protocolo en sí.
6.7 Formatos de datos y medios de transferencia
Antes del Transferencia de Datos Uniforme, prácticamente todos los protocolos
estándares fueron bastante débiles para describir los datos que estaban siendo
transferidos y por lo regular se requería que el intercambio ocurriera a través de una
memoria global.
El problema con el formato del clipboard es que este puede solamente describir la
estructura de los datos, esto es, identifica la composición de los bits. Por ejemplo el
formatos CF-TEXT describe un texto ASCII, el CFBITMAP describe un dispositivo
dependiente de un mapa de bis y así tanto colores como tal dimensiones, pero fue
incapaz de describir el mecanismo de sobre que depende. Además ninguno de estos
mecanismo o dispositivos dio alguna indicación de Io que realmente estaba en los datos,
tal como la cantidad de detalles, si era un mapa de bit o un metafile de imágenes llenas.
El problema con el uso de la memoria global como un medio de transferencia es
aparente cuando una gran cantidad de datos es intercambiado. Restringiendo los
intercambios a la memoria global significa que ninguna aplicación puede seleccionar los
datos de intercambio que están en el disco cuando esta vaya a residir en disco, aún
cuando sea manipulado y vaya a usar memoria virtual. Esto podría ser mucho más
eficiente que permitir que el origen de los datos indique que el intercambio sucede en
disco in primer lugar en lugar de forzar los 20 MB de datos por medio de un cuello de
botella en memoria virtual
A veces se necesita comenzar el proceso con el comienzo de largo conjunto de
datos antes de que el fin del conjunto de datos haya alcanzado la computadora destino.
Para alcanzar esto, alguna abstracción sobre el medio por el cual los datos son
transferidos es necesitada.
Para resolver este problema, COM define 2 estructuras de datos FORMATECTC y
STGMEDIUM. El primero es un formato clipboard mejor, por que la estructura no solo
contiene un formato de clipboard sino que también contiene una descripción del
mecanismo, una descripción detallada (contenido, etc.) y una bandera que indica qué
dispositivo de almacenamiento es usado para una interpretación en particular. Dos
estructuras FORMATETC que difieren solamente por el medio de almacenamiento, son 2
diferentes formatos. EL STGMEDIUM es entonces mejor para el manejo global de
memoria, el cual tiene una bandera para indicar el medio además del apuntador o manejo
71
Cap. 6 Ambiente Cliente/Servidor bajo COM
de cualquiera que sea necesario para tener acceso al medio real y conseguir los datos.
Dos estructuras STGMEDIUM pueden indicar diferentes medios y tener diferentes
referencias a los datos, pero estos medios pueden fácilmente obtener los mismos datos.
FORMATECT es lo que un Cliente utiliza para indicar el tipo de datos que desea
de una fuente de datos (objeto o Servidor) y es usado por la fuente para describir qué
formatos puede proporcionar. FORMATECT puede describir Prácticamente cualquier dato,
incluyendo otros objetos tal como un monikers. Un Cliente puede pedir un objeto de datos
para una enumeración de sus formatos pidiendo al objeto de datos una interface
IEnumFORMATECT.
STGMEDIUM significa que la fuente de datos y los consumidores pueden ahora
escoger el uso del más eficiente medio de intercambio en una base de ***Si los datos son
muy largos, esto podrían ser guardados en disco, la fuente de datos puede indicar un
medio de disco basado en su formato preferido, solamente usando la memoria global
como respaldo si esto es todo lo que el Cliente entiende. Esto tiene el beneficio de usar el
mejor medio para los intercambios por default, además mejora la ejecución de
intercambios entre las aplicaciones
En el peor de los casos, los mecanismos de COM podría ser tan buenos como
cualquier protocolo de transferencia de memoria global disponible hoy en día, y en el
mejor, los intercambios de datos podrías ser casi instantáneos aún con muchos datos.
Nota que 2 medios potenciales de almacenamiento que pueden ser usados en
intercambio de datos son los objetos de almacenamiento y los objetos de flujo
6.8 Responsabilidades de una aplicación COM
0
0
o
Verificar que la Librería COM sea una versión compatible con la función COM
CoBuilVersion
Inicializar las librería COM antes de usar cualquier otra función, llamando la función
Colnitialize
Desinicializarse de la Librería COM con la función CoUninitializeg
72
Cap. 7 Aplicación
7.1 Objetivo
El objetivo de esta aplicación es implementar un modelo Cliente/Servidor utilizando
COM, ya que este nos permite que la comunicación entre estos dos componentes sea
transparente (es decir, que el usuario no sabe que se comunica con la Base de Datos a
través de un objeto), segura, independientemente del leguaje de programación en el cual
se implementa cada uno.
Hay que tener presente que la utilización de COM en una aplicación que realice
accesos a Bases de datos no es la más optima, pero debido a que las Bases de Datos
son más familiares para cualquier programador se decidió implementar este tipo de
aplicación.
7.2 Descripción
El Sistema se encarga del manejo de información de un Centro de Renta de Video,
para el cual se construyó una Base de Datos en Access 97 y se implementó en Visual
Basic Versión 5.0 Entrepise, bajo el modelo Cliente/Servidor.
El Servidor (Objeto COM) es el que se encarga del acceso y manejo a la Base de
Datos, mediante sentencias SQL. El Cliente hace uso de ese objeto a través de peticiones
(consultas, inserciones, etc.), cabe mencionar que el Servidor puede tener varias
instancias para atender a varios Clientes a la vez.
Con el objetivo de tener integridad y validación de la información en la Base de
Datos, se implementó en el Servidor la concurrencia, se asignaron roles a los diferentes
usuarios (Clientes), a demás de que el Servidor controla el acceso a los datos que están
siendo utilizados por otra instancia.
Para que el Servidor pudiese manejar las diferentes instancias, sin necesidad de
duplicarse, se implementó como un ActiveXEXE en Visual Basic y el Cliente como un
StandarEXE. El Servidor esta constituido exclusivamente por clases y sus respectivos
métodos y se utilizó una interface para indicar la existencia se esté.
7.3 Descripción del Diseño
7.3.1 Base de Datos
De acuerdo a los requerimientos establecidos se hizo el análisis y diseño de base
al modelo relacional. A continuación se muestra el Modelo Entidad-Relación que se
obtuvo:
73
Cap. 7 Aplicación
7.3.2 Cliente
El Cliente maneja las diferentes interfaces gráficas con el usuario (formularios), las
cuales le proporciona un manejo de Altas, Bajas, Cambios y Consultas; que puede
realizar tanto para los Clientes, Videos y Empleados, así como permitirle realizar
Préstamos y Devoluciones de un video. También maneja las interfaces con el Servidor
(Objeto COM).
Se muestra a continuación un Diagrama de Transición de Estados, en donde se
puede observar el funcionamiento del Cliente. Nótese que el Cliente interactua con el
Servidor solo cuando hace uso de la Base de Datos.
74
Cap. 7 Aplicación
DIAGRAMA DE TRASICIÓN DE ESTADOS
DEL CLIENTE
[
VIDEO CLUBESPARTACUS
MtoClientes
MANTENIMIENTO A CLIENTES
Pantalla Anterior
MtoEmpleados
Pantalla Anterior
MANTENIMIENTO A EMPLEADOS
II
'
I
MtoVideos
>
Pantalla Anterior
MANTENIMIENTO A VIDEOS
PresIDevol
Pantalla Anterior
I
O
1
VIDEO CLUB ESPARTACUS
i
1
ALTAS
MANTENIMIENTO A CLIENTES
J
Pantalla Anterior
Agregar Registro I InsertBD
i
L'
Pantalla Anterior
Baja de Clientes
Eliminar Registro I DeleteBD
Agregar Cambio I UpdateDB
CON SU LTAS
Pantalla Anterior
'
W
Consulta[ Sel. un Cliente ]
Consulta Cliente
Pantalla Anterior
75
Cap. 7 Aplicación
.
A
VIDEO CLUB ESPARTACUS
ALTAS
MANTENIMIENTO A EMPLEADOS
I
?A i
Pantalla Anterior
I<
Agregar Registro I InsettBD
BAJAS
Pantalla Anterior
Eliminar Registro I DeleteBD
Agregar Cambio I UpdateDB
CONSULTAS
Pantalla Anterior
1
I
Consulta[ Sel. un Empleado ]
Consulta Empleado
Pantalla Anterior
VerMenuPrinrjpal
NUEVO TITULO
~
AUadeTítulo
Panialla Anterior
Agregar RegisBoI Insert
~
V
P a d l a Anterior
ALTAVIDEO
i
NUEVO EJEMPLAR
* EJm@ar
Agregar Registro I IIISW~ED
Panialla Anterior
BAJATITULO
i
‘daiadeTítulo
i
76
Cap. 7 Aplicación
O
VIDEO
am ESPARTACW
1
VIDEO CLUB ECPARTACUS
Pantalla Anterior
>
>
Devolución
77
Cap. 7 Aplicación
7.3.3
Servidor
El Servidor maneja la interface con la Base de Datos (llamadas SQL), las cuales la
actualizan o consultan, de acuerdo a la petición hecha por el Cliente. También maneja
interfaces con el(los) Cliente(s) (instancias), por medio de las diferentes clases de
consultas, inserciones, actualizaciones y eliminaciones; enviándole el resultado de cada
una de ellas.
Se muestra a continuación un Diagrama de Objetos, en donde se puede observar
el funcionamiento del Servidor.
DIAGRAMAS DE OBJETOS DEL SERVIDOR
1: Selección Opción
2: Mostrar()
1
\ I
I rf
3: Captura o Selección de Datos
+
4: Aceptar
+
5: AtiendePeticiónCliente(DatosCliente)
I
+
I
-
L__-l
I
I
I
ObjCliente
I
I
I
IJ
6: InteractuaD B(Datos)
El objeto "ObjCliente" cuenta con las sigLlzntes clases, las cuales incluyen sus
propios métodos, estos se ejecutan de acuerdo a la petición hecha por el Cliente en el
paso 5 del diagrama anterior:
ObjCliente
ClaseAltaCliente (ClaseAltaCliente.cls)
ClaseCambioCliente (ClaseCambioCliente,cls)
Clasecvecliente (claseCveClienteaCIS)
ClaseEliminarChte (ClaseElinarUiente, cls)
ClaseExiste (ClaseExiste.cls)
ClaseGetCveCliente(ClaseGetCveCliente,cis)
ClaseGetCveCte (ClaseGetCveCteds)
78
Cap. 7 Aplicación
1: Selección Opción
2: Mostrar()
5: At iendePeticiónEmpleado(DatosEmpleado)
ObiEmDleado
3: Captura o Selección de Datos
--+
+
I
4: Aceptar
I
I$
6: InteractuaDB(Datos)
El objeto "ObjEmpleado" cuenta con las siguientes clases, las cuales incluyen sus
propios métodos, estos se ejecutan de acuerdo a la petición hecha por el Cliente en el
paso 5 del diagrama anterior:
ObjEmpleado
ClaseAtaEmpleado (ClaseAltaEmpleado.cls)
claseCambioEmpleado (claseCambioEmpleado.cls)
ClaseCveEmpleado (ClaseCveEmpleado.cls)
ClaseEliminarEMPLEADO(daseEliminarEMPLEAD0,cls)
ClaseGetCveEmp (daseGetCveEmp.cls)
ClaseGetCveEmpleado(ClaseGetCveEmpleado,CIS)
79
Cap. 7 Aplicación
lnteríaz
2: Mostrar()
it7-7
5: Envia Petición Video(Datos Video)
Video
--+-
Obivideo
El objeto "ObjVideo" cuenta con las siguientes clases, las cuales incluyen sus
propios métodos, estos se ejecutan de acuerdo a la petición hecha por el Cliente en el
paso 5 del diagrama anterior:
ObjVideo
ClaseActor (ClaseActords)
ClaseAltaActor (ClaseAltaActor .CIS)
ClaseCambioTema (ClaseCambioTema.CIS)
ClaseCambioTitulo(ClaseCambioTitulo.CIS)
ClaseEjemplares (ClaseEjemplar es.cls)
ClaseEliminarEjem (ClaseEliminarEjern.cls)
ClaseEliminarTkulo (ClaseEliminarTkulo.CIS)
ClaseGetCveActor (ClaseGetCveActor.CIS)
ClaseGetCveTema (CkeGetCveTema.cls)
ClaseGetCveTkulo (ClaseGetCveTkulo.cls)
ClaseGetCveTkuloClas(ClaseGetCveTituloCIasLIS)
ClaseGetEjem (ClaseGetEjem.cls)
ClaseGetFormato(ClaseGetFormato.cls)
ClaseNuevaCveActor (ClaseNuevaCveActor.cis)
ClaseTerna (ClaseTerna.cls)
80
Cap. 7 Aplicación
1: Selección Opción
lnterfaz
5: Envia Petiaón Pkstíüev(Datos P k d D e v )
+
I
ObiPkU'üev
I
3: Captura o S e l e d ó n de Datos
II
__3
4: Aceptar
+
6: InteractuaDB(Dat0s)
El objeto "ObjPréstamo/DevoluciÓnll cuenta con las siguientes clases, las cuales
incluyen sus propios métodos, estos se ejecutan de acuerdo a la petición hecha por el
Cliente en el paso 5 del diagrama anterior:
I
ObjPrédDev
I
ClaseDevolucion (ClaseDevolucibn,cls)
ClaseGetFolio (ClaseGetFolio,cls)
ClasePréstamo (ClasePréstamo,cls)
81
Cap. 7 Aplicación
7.4
Implementación
7.4.1 Creación de la aplicación Cliente.
0
Como ya se había mencionado antes, el Cliente se implementó como un Standard
EXE en Visual Basic, así que en la ventana de "New Project'' se seleccionó como
sigue:
ActiveX DLL
VE Enterprise
Addin
Acthiex
Cmbd
VE Appkatiwi
Wizard
ActiveX
ActiveX
Daurnent DLL Document EXE
Se tiene que revisar que se tengan las referencias necesarias (en el menú Project)
para la aplicación, ya que sin estas se pueden producir errores cuando se realice la
ejecución de la aplicación, en nuestra aplicación serán necesarias las siguientes
referencias:
82
Cap. 7 Aplicación
Se realizó el diseño con la ayuda del Toolbox, las diferentes interfaces que son
necesarias para la aplicación. La primera interface que se muestra, pide el Nombre
del Usuario y su Password, ya que con estos datos se realiza una verificación para
saber el acceso con el que cuenta el usuario y posteriormente mostrarle otra
interface (Principal) con la cual puede hacer uso del sistema, ya que cuenta con las
opciones de: Mantenimiento a Clientes, Mantenimiento a Empleados, Mantenimiento
a Videos y Préstamo y Devoluciones; dichas interfaces son las siguientes:
AI hacer click en Mantenimiento de Clientes o Mantenimiento de Empleados, se
desplegará otra interface, en la cual se pueden realizar: Altas, Bajas, Cambios y
Consultas sobre la Base de Datos. Cuando se realiza una Alta de Cliente (o
Empleado) se muestra una nueva interface, en donde el usuario debe de
proporcionar los datos que se le piden y hacer click en el botón de Agregar Registro
para que agregue a la Base de Datos. AI realizar una Baja de Cliente (O Empleado)
se mostrará una interface, la cual pide la clave del empleado y el Cliente, hacer
click en el botón de Eliminar Registro para darlo de baja en la Base de Datos.
Dichas interfaces son las que a continuación se muestran:
83
Cap. 7 Aplicación
Sí se realiza un Cambio de Cliente (o Empleado) o una Consulta de Cliente (o
Empleado), se muestra una interface, en donde se selecciona el cliente y
posteriormente otra en la cual se despliegan los datos del cliente, en el caso de
realizar un cambio se hace click en el botón de Agregar Cambio para realizarlo en la
Base de datos. Se muestran las interfaces:
Ai hacer click en Mantenimiento de Videos, se despliega una interface para que el
usuario pueda hacer: Altas, Bajas, Cambios y Consultas a los Videos. AI seleccionar
Alta de Video, se muestra una interface en donde se piden ciertos datos, ai hacer
click en el botón de Agregar Registro, se muestra otra interface en donde se
selecciona el Autor, en caso de que el autor que se quiera no exista se tendrá que
dar de alta a través del botón Alta Actor y para seleccionar el Tema hacer click en el
botón Agregar Tema. Las interfaces descritas son las siguientes:
84
Cap. 7 Aplicación
Sí se selecciona Baja de Video, se muestra una interface en donde se elige si la
baja será por Título o por Ejemplar, posteriormente se muestra otra interface
dependiendo de la elección; en la interface de eliminar por título, se elige este y se
hace click en Eliminar Registro para eliminarlo de la Base de Datos; en la interface
de eliminar por ejemplar, se debe de elegir tanto el título como la colocación y
posteriormente hacer click en Eliminar Registro para eliminarlo de la Base de Datos.
Se muestran a continuación dichas interfaces:
85
Cap. 7 Aplicación
AI seleccionar Cambios de Video, se muestra una interface en donde se elige el
título, posteriormente se muestra otra en donde se pueden realizar cambios tanto al
Título como ai Tema y Actor, si se quieren hacer cambios en tema y actor hacer
click en el botón CambioTema o CambioActor según se quiera. Una vez hechos los
cambios hacer click ai botón Agregar Cambio, para actualizar la Base de Datos. La
interface es la siguiente:
Si se selecciona Consulta de Video, se muestra una interface en donde se tiene la
opción de hacer consultas por: Título, Actor y Tema. AI seleccionar cualquiera de
estas se muestra otra interface en donde se elige un título, un actor o un tema
según sea el caso; posteriormente se muestran los datos correspondientes a cada
uno de estos a través de otra interface. A continuación se muestran estas:
86
Cap. 7 Aplicación
AI hacer click en Préstamo/DevoluciÓn se muestra una interface en donde se elige si
se quiere hacer una devolución o un préstamo; si se selecciono Préstamo, se
muestra otra interface en donde se elige el título, formato y precio, hacer click en
Agregarpréstamo por cada préstamo de video que se quiera hacer en la Base de
Datos se colocará un status. Si se selecciono Devolución se muestra una interface
para elegir el folio de la devolución y posteriormente otra en donde se muestran los
préstamos correspondientes a ese folio. AI hacer click en DecoluciónPréstamo en la
Base de Datos se quita el status que tiene relacionado el ejemplar. Se muestran las
interfaces a continuación:
87
Cap. 7 Aplicación
0
Finalmente se escribió todo el código necesario para que las interfaces se
relacionen entre sí y lo que es más importante, la creación del objeto con el cual el
Cliente se comunica con el Servidor.
En el código que a continuación se muestra: la primer línea se encarga de crear el
objeto, la variable Objeto tendrá que ser de tipo Object, el primer parámetro que se
encuentra dentro de los paréntesis es el nombre del Servidor al que se va ha
conectar y el segundo parámetro es la clase a la que va ha accesar; la sugunda
línea ejecuta el procedimiento del objeto (clase), la variable Res deberá ser del
mismo tipo del que regresa la función, el primer parámetro es el nombre del objeto
que se creó seguido del nombre del procedimiento a ejecutar y si este recibe
variables de entrada se escribirán dentro de los paréntesis como sigue:
Dim Objeto As Object
Set Objeto = CreateObject("Servidor.Clase")
Res = Objeto.Procedimiento(Text1,Text2, ... ,Textn)
7.4.2 Creación de la aplicación Servidor
0
Como ya se había mencionado antes, el Servidor se implementó como un ActiveX
EXE en Visual Basic, así que en la ventana de "New Project" se seleccionó como
sigue:
88
Cap. 7 Aplicación
Se tiene que revisar que se tengan las referencias necesarias (en el menú Project)
para la aplicación, ya que sin estas se pueden producir errores cuando se realice la
ejecución de la aplicación, en nuestra aplicación serán necesarias las siguientes
referencias :
0
La aplicación Servidor, solo cuenta con una interface, la cual nos permite tener un
control del número de instancias que se conectan con el Servidor. A continuación se
muestra dicha interface:
.........................
......................................
......................................
......................................
..
'
Base de Datos
..
..
. Cliente
..
.: .:
.. ..
I
..
..
..
..
.. ..
..
. Empleado .. ..
...
... ... ... Video
.. .. .. Prestamo
..
.. ..
..
.. ..
. . .. ..
....
....
....
....
....
89
Cap. 7 Aplicación
0
Finalmente se escribió el código necesario para las clases, las cuales accesan la Base
de Datos; también el código que bloquea o libera las instancias conectadas al Servidor
dependiendo de la petición, las cuales pueden ser: Cliente, Empleado, Video,
Préstamo. A continuación se muestra este código:
Public Sub BloqueaCliente()
If IsNumeric(FrmServidor.Cliente.Caption)
Then
FrmServidor.Cliente.Caption= "2"
Else
FrmServidor.Cliente.Caption= "1
End If
End Sub
I'
Public Sub Liberacliente()
FrmServidor.Cliente.Caption=
End Sub
I'
7.4.3 Generación de Setup para la aplicación Cliente-Servidor Remote Automation Ó
COM
Si la aplicación utiliza un componente ActiveX , el Wizard proporciona un medio
para crear setup's tanto para el cliente y como para servidor en un ambiente de Remote
Automation Ó COM.
A continuación se muestra como creo un setup para una aplicacion
Cliente/Servidor y presenta las posibles opciones tanto para un Remote Automation como
paraun COM.
7.4.3.1 Creación del setup para el servidor:
1. Inicializar el Setup Wizard.
2. Hacer click en el botón Next para seleccionar la pantalla Select Project and Option.
3. Escoger el nombre del Servidor, tecleando la ruta y el nombre del archivo dentro de la
caja de entrada Project File, Ó seleccionar el botón Browse para buscarlo.
90
Cap. 7 Aplicación
4. Seleccionar la opción Create a Setup Program, hacer click en el botón Next para
proseguir. Si se desea que el Setup Wizard construya tu proyecto, checar la opción
Rebuil the Project.
5. Proseguir hasta la pantalla Shared ActiveX Applications.
Seleccionar Install as shared component y
Automation Ó No si se desea usar COM.
Yes si se desea usar Remote
Si se selecciona Remote Automation, los archivos Racmgr32.exe, Racreg32.dl1,
Autprx32.dll y Autmgr32.exe serán agregados al setup.lst e instalados con la aplicación
servidor en el directorio \Windows\System del servidor remoto.
6. Proseguir hasta crear el setup para el servidor.
Esta aplicación servidor se instala en la computadora remota. El setup de esta aplicación
instalará los archivos necesarios.
91
Cap. 7 Aplicación
7.4.3.2 Creación del setup para el cliente:
1. Antes de proseguir, asegurarse de que se tiene creado el archivo .vbr para cada
servidor remoto que se haga referencia en la aplicación. Crear un archivo .vbr
seleccionando la opción Remote Server Component de la caja de diálogo Project
Properties en Visual Basic y luego compilar el proyecto.
2. Comenzar el Setup Wizard.
3. Hacer click en el botón Next para seleccionar la pantalla Select Project and Option.
4. Escoger el proyecto servidor tecleando la ruta y el nombre del archivo dentro de la
caja de entrada Project File Ó seleccionar el botón Browse para buscarlo.
5. Seleccionar la opción Create a Setup Programa y luego hacer click en el botón Next
para proseguir. Si se desea que el Setup Wizard construya el proyecto, checar la
opción Rebuil the Project.
NÓTESE QUE: Antes de crear el setup para el cliente se deberá de tener compilada la
aplicación por lo menos una vez en Visual Basic.
6. Seleccionar la opción distribución y localización, proseguir a la pantalla ActiveX
Components.
Si el proyecto cliente contiene referencias al servidor local, la aplicación servidor será
listada en la caja de archivos.
92
Cap. 7 Aplicación
Si se quiere agregar servidores remotos, hacer click en el botón Add Remote.
7. En el prompt solamente se verán los archivos *.vbr de la aplicación servidor. Localizar
el archivo en el directorio fuente del proyecto servidor y escoger Open. El archivo .vbr
será agregado a una lista de archivos, y aparecerá un diálogo correspondiente
Remote Connection Details en donde se escribirá información de la conexión.
Si se está usando DCOM, escoger la opción Remote Transport y luego escribir el
nombre del servidor remoto en la caja de entrada Network Addresss.
Si se está usando Remote Automation, seleccionarlo y luego especificar cualquier
dirección de red válida, el protocolo de la red y los niveles de verificación, los cuales se
pueden dejar en blanco si se quiere que el cliente Ó el usuario escriba esta información a
tiempo de instalación.
Seleccionar las opciones apropiadas y hacer click en el botón OK para regresar a
la pantalla ActiveX Components. Si tanto la versión local (.exe) y remota (.vbr) aparecen
en la lista de los componentes, se debe de eliminar la versión local (.exe). de tal forma
que solamente el servidor remoto sea usado por la aplicación cuando sea instalado.
93
Cap. 7 Aplicación
8. Proseguir a través del Setup Wizard para crear el setup cliente .
Instalar la aplicación cliente en la máquina del usuario cliente y seguir los
procedimientos de Remote Automation o DCOM usando la aplicación cliente-servidor.
94
Conclusiones
El vertiginoso desarrollo de los lenguajes de programación ha propiciado la
actualización y orientación de sistemas cada vez más complejos, los que por diseño,
deberán de cumplir con una serie de requisitos, tales como:
0
El uso del análisis orientado a objetos en el diseño del sistema, el cual reduce en un
gran porcentaje el esfuerzo en el desarrollo de la aplicación y proporciona la
facilidad de crear una implementación, en la cual se puede representar la
interacción de los objetos, en una equivalente a la del mundo real.
La portabilidad de los programas debido a la existencia creciente de múltiples
plataformas que prevalecen en el mercado.
Las interfaces gráficas que hacen que los diseños sean más amigables con los
usuarios, acortando la brecha semántica entre la máquina y el ser humano.
Es por eso que para la implementación de la aplicación, posteriormente de un
análisis y diseño orientado a objetos, se hace indispensable contar con un lenguaje de
programación que soporte estos métodos; en Visual Basic ver. 5.0 encontramos el
lenguaje que proporciona las ventajas de la metodología y su gran capacidad de crear
programas flexibles y modulares, así como la reutilazación de código establecido,
haciéndose apropiado para el desarrollo de Sistemas Distribuidos.
Como se observa en el diagramas de Transición de Estados y de Objetos, el
análisis y diseño orientado a objetos hace que la implementación del sistema se reduzca
en gran porcentaje, tanto en código como en esfuerzo, a diferencia que si se hubiese
implementado con otra metodología. Los procesos que fueron implementados en esta
aplicación son mecanismos que proporciona Visual Basic, el cual permite crear una gran
variedad de interfaces gráficas con mucha sencillez.
Como se ha mencionado, COM ofrece el protocolo que permite a una aplicación
interactuar con otra en la misma máquina, pero dada las necesidades mencionadas
anteriormente ahora lo que se busca es la capacidad de comunicar aplicaciones
funcionando en máquinas distintas dentro de una red. Esto es esencialmente lo que
ofrece DCOM. Este protocolo de comunicación conjuntamente con la creación de objetos
permite el desarrollo de Sistemas Distribuidos.
95
Conclusiones
El protocolo de comunicación que ofrece DCOM para el desarrollo de Sistemas
Distribuidos cubre siguientes funciones:
Control de conexión .- DCOM utiliza un contador de referencia para determinar
cuántos clientes están conectados a un determinado servidor.
Control de flujo
Sincronización
Control de desconexión .- Cuando el contador de referencia llega a cero, la aplicación
se cierra. Cuando un servidor de aplicaciones ya no esté en funcionamiento, DCOM
lanzará la aplicación y establecerá el contador de referencia de la manera más
adecuada.
El gran desarrollo tecnológico que se ha dado sobre las redes de comunicación (la
internet), acorta cada vez más las distancias y los tiempos de respuesta. Estos dos
grandes factores, motivaron la realización de una Aplicación Cliente/Servidor utilizando el
protocolo de comunicación DCOM.
Resumen de logros
Realmente la parte importante de este proyecto fue el hecho de haber logrado una
documentación explícita de lo que se refiere a la metodología COM, es decir, se deja una
buena documentación conceptual de lo que es la construcción de los objetos COM.
En lo que se refiere a la parte técnica, se logro establecer la comunicación con los
objetos COM desde una aplicación normal, ya sea en una misma máquina Ó en máquinas
distintas.
Por otra parte, la documentación presentada indica que lo mas conveniente para
la implementación de un objeto COM es la utilización del lenguaje C, por lo que podemos
considerar que esta parte no fue cubierta por el presente proyecto. Sin embargo la
implementación de éste se hizo utilizando Visual Basic 5.0 y así mismo la aplicación que
utiliza este objeto también fue implementada en la misma herramienta.
96
Conclusiones
Propuesta de lmplementaciones Futuras en el Proyecto
Manejar aún mas la reutilización de código, específicamente en las clases que
maneja el Servidor, para la optimización de tiempo de desarrollo.
0
Distribuir la carga de la aplicación Servidor, es decir, que se tenga un servidor para
cada una de las entidades (Cliente, Empleado, Video, Préstamo/Devolución)
realizando todas sus operaciones involucradas (Altas, Bajas, Cambios y Consultas).
0
Estos servidores podrían ser codificados en diferentes lenguajes de programación
(Delphi, Visual C, Visual Java, etc) y ser accesados por el mismo cliente (sin tener
que modificarlo) ya que esto lo soporta DCOM.
Agregar nuevas funcionalidades al Sistema de Videos para que su implementación
se asemeje al mundo real. Por ejemplo que el sistema maneje Promociones,
Proveedores, Finanzas , etc.
Codificar los objetos COM en C, en base a los conceptos que se describen en el
presente resumen.
97
Bibliografía
Berson Alex
ClientEerver Architecture
McGraw-Hill, 1992
Dwana Travos
ClienüServer Computing
McGraw-Hill, 1993
Vaughn Larry T.
ClienüServer System Design and Implementation
McGraw-Hill, 1994
98
Descargar