Академический Документы
Профессиональный Документы
Культура Документы
SERDN
COM/DCOM/RMI
PORFIRIO MEDINA DE LA ROSA
MATRICULA 13CS0296
SEXTO SEMESTRE
COM/DCOM
Tipos de componentes
Los componentes COM se pueden agrupar bsicamente en tres categoras.
Los componentes In-Process se cargan en el mismo espacio de procesos que la
aplicacin cliente. Estos componentes se implementan como libreras dinmicas
(DLL) por lo cual se minimiza el tiempo requerido para la invocacin de los
mtodos. Por otra parte, como el componente comparte el espacio de direcciones
de la aplicacin, una falla en el componente puede causar daos en la aplicacin.
Los componentes In-Process no son programas ejecutables, por lo tanto solo
pueden usarse en el contexto de un programa que los invoca. Los controles
ActiveX son componentes In-Process.
Los componentes locales se ejecutan en un proceso separado en el mismo
computador mientras que los componentes remotos se ejecutan en otro
computador. La aplicacin cliente no necesita saber dnde reside el componente.
Ejemplo
El cliente
Abajo se muestra el programa cliente. ste usa el componente COM cuya
interface se defini en la seccin 6. Aunque este programa verifica las condiciones
de error luego de cada llamada, cuando ocurre un error slo se muestra un
mensaje y se permite que el programa contine su ejecucin. Esto es una mala
prctica y solo se justifica en este caso debido a que un buen manejo de errores
complicara el el programa y dificultara la comprensin de los conceptos COM
ilustrados.
// client.cpp
#include <iostream.h>
#include "component.h" // Generated by
MIDL
//
{10000002-0000-0000-0000000000000001} const CLSID CLSID_MySum =
{0x10000002,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}};
void main()
{
cout << "Client: Calling CoInitialize()" << endl;
HRESULT
hr
=
CoInitialize(NULL);
if(FAILED(hr))
cout << "CoInitialize failed" << endl;
IUnknown* pUnknown;
ISum* pSum;
cout << "Client: Calling CoCreateInstance()" << endl; hr =
CoCreateInstance(CLSID_MySum, NULL, CLSCTX_INPROC_SERVER,
IID_IUnknown,
(void**)&pUnknown);
if(FAILED(hr))
cout << "CoCreateInstance failed" << endl;
cout << "Client: Calling QueryInterface() for ISum on " <<
pUnknown << endl;
hr
=
pUnknown->QueryInterface(IID_ISum,
(void**)&pSum);
if(FAILED(hr))
cout << "IID_ISum not supported" << endl;
hr = pUnknown->Release();
cout << "Client: Calling pUnknown->Release() reference count = "
<< hr << endl;
int sum;
hr
=
pSum->Sum(2,
3,
&sum);
if(SUCCEEDED(hr))
cout << "Client: Calling Sum(2, 3) = " << sum << endl;
hr = pSum->Release();
cout << "Client: Calling pSum->Release() reference count = " <<
hr << endl;
Funciones DLL
Dado que el componente es InProcess, ste estar contenido en un DLL. Adems
de lo mencionado hasta ahora, este DLL debe exportar dos funciones:
$
$
El componente
Para construir el componente se debe crear un proyecto que contenga
component.def, component.cpp y el archivo componente .c generado por MIDL.. El
cdigo del componente se muestra abajo:
// component.cpp
#include <iostream.h> // For cout
#include "component.h" // Generated by MIDL
// {10000002-0000-0000-0000-000000000001}
const CLSID CLSID_MySum =
{0x10000002,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}};
long g_cComponents = 0;
long g_cServerLocks =
0;
HANDLE g_hEvent; // For a later exercise with local components
class CMySum : public ISum
{ pu
blic
:
// IUnknown
ULONG __stdcall AddRef();
ULONG __stdcall Release();
HRESULT __stdcall QueryInterface(REFIID iid, void** ppv);
// ISum
HRESULT __stdcall Sum(int x, int y, int* retval);
CMySum() : m_cRef(1) { g_cComponents++; }
~CMySum() { cout << "Component: CMySum::~CMySum()" << endl,
g_cComponents--; }
priv
ate:
ULONG m_cRef;
};
ULONG CMySum::AddRef()
{
endl;
}
ULONG CMySum::Release()
{
cout << "Component: CMySum::Release() m_cRef = " << m_cRef - 1 <<
endl;
if(--m_cRef != 0)
return m_cRef;
delete this;
return 0;
}
HRESULT CMySum::QueryInterface(REFIID iid, void** ppv)
{
if(iid == IID_IUnknown)
{
cout << "Component: CMySum::QueryInterface() for IUnknown
returning " << this << endl;
*ppv = (IUnknown*)this;
}
else if(iid == IID_ISum)
{
cout << "Component: CMySum::QueryInterface() for ISum returning "
<< this << endl;
*ppv = (ISum*)this;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
HRESULT CMySum::Sum(int x, int y, int* retval)
{
cout << "Component: CMySum::Sum() " << x << " + " << y << " = " << x + y
<< endl;
*retval = x + y;
return S_OK;
}
class CFactory : public IClassFactory
{ pu
blic
:
// IUnknown
ULONG __stdcall AddRef();
ULONG __stdcall Release();
HRESULT __stdcall QueryInterface(REFIID iid, void** ppv);
// IClassFactory
HRESULT __stdcall CreateInstance(IUnknown *pUnknownOuter, REFIID iid,
void** ppv);
HRESULT __stdcall LockServer(BOOL bLock);
CFactory() : m_cRef(1) { }
~CFactory() { }
priv
ate:
};
ULONG m_cRef;
ULONG CFactory::AddRef()
{
cout << "Component: CFactory::AddRef() m_cRef = " << m_cRef + 1 <<
endl;
return ++m_cRef;
}
ULONG CFactory::Release()
{
cout << "Component: CFactory::Release() m_cRef = " << m_cRef - 1 <<
endl;
if(--m_cRef != 0)
return
m_cRef;
delete this;
return 0;
}
HRESULT CFactory::QueryInterface(REFIID iid, void** ppv)
{
if((iid == IID_IUnknown) || (iid == IID_IClassFactory))
{
cout << "Component: CFactory::QueryInteface() for IUnknown or
IClassFactory " << this << endl;
*ppv = (IClassFactory *)this;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
HRESULT CFactory::CreateInstance(IUnknown *pUnknownOuter, REFIID iid,
void** ppv) {
if(pUnknownOuter != NULL)
return CLASS_E_NOAGGREGATION;
CMySum *pMySum = new CMySum;
cout << "Component: CFactory::CreateInstance() " << pMySum << endl;
if(pMySum == NULL)
return
E_OUTOFMEMORY;
Ntese que componet.cpp contiene dos clases. La clase CMySum que implementa
las clases IUnknown e ISum, mientras que la clase CFactory implementa
Iunknown e IclassFactory.
[HKEY_CLASSES_ROOT\CLSID\{10000002-0000-0000-0000000000000001}\InprocServer32]
@="C:\\Program
Files\\DevStudio\\MyProjects\\Component\\Debug\\Component.dll"
DCOM
DCOM proporciona esta
transparencia: DCOM puede
utilizar cualquier protocolo de
transporte, como TCP/IP, UDP,
IPX/SPX y NetBIOS. DCOM
proporciona un marco de seguridad
a todos estos protocolos.
Hay
muchos
libros,
herramientas y desarrolladores.
Microsoft depende
funcionamiento.
Es
difcil
mantener
una
consistencia en el registro.
de
su
No
soportado
lenguajes.
RMI
RMI es un paquete de JAVA que
permite manejar objetos (y sus
respectivos
mtodos)
de
manera remota, para utilizar los
recursos de un servidor de
manera transparente para el
usuario local.
por
otros