Title: Systemy rozproszone
1Systemy rozproszone
Uniwersytet Lódzki Katedra Informatyki
W. Bartkiewicz
Wyklad 5. Komunikacja miedzyprocesowa z
wykorzystaniem uslug warstwy posredniej zdalne
obiekty Czesc 2
2Ewolucja COM
3COMInterfejsy
- COM korzysta z modelu obiektu zdalnego. Obiekty
COM umieszczane moga byc - w procesie klienta,
- w procesie na tej samej maszynie co klient,
- w procesie na maszynie zdalnej.
- Podobnie jak CORBA, COM skupia sie na realizacji
interfejsów. Obiekt COM jest generalnie
realizacja interfejsu. Jeden obiekt moze
realizowac kilka interfejsów. - Do definiowania interfejsów wykorzystywany jest
jezyk opisu interfejsu Microsoft IDL (MIDL). - W przeciwienstwie do CORBY interfejsy COM maja
charakter binarny. Sa to tablice wskazników do
funkcji bedacych jego czesciami.
4COMInterfejsy binarne i zalezne od jezyka
Interfejsy binarne
Wskazniki do funkcji
Kompilator z IDL na interfejs
Specyfikacja IDL
Tablica funkcji
Interfejsy zdefiniowane w jezyku
Definicje klas Javy
Definicje klas C
Kompilator z IDL na jezyk
Kompilator konkretnego jezyka
Prototypy C
5COMInterfejsy
- W srodowisku CORBA standaryzacja interfejsów
odbywa sie na poziomie zródlowym, tzn.
standardowy charakter ma IDL oraz odwzorowanie
jego specyfikacji na dany jezyk programowania. - W COM standaryzacja odbywa sie na poziomie
binarnym. Kompilator interfejsów generuje
standardowa postac binarna interfejsu, która
wykorzystana moze byc w dowolnym jezyku
programowania. - Kazdy interfejs COM ma jednoznaczny 128 bitowy
identyfikator, zwany identyfikatorem interfejsu
(IID Interface Identifier). Kazdy IID jest
globalnie jednoznaczny, tzn. nie ma dwu
interfejsów o tym samym IID. Generowany jest na
podstawie adresu interfejsu sieciowego danego
komputera, czasu oraz duzej liczby losowej.
Prawdopodobienstwo wygenerowania dwu takich
samych IID jest praktycznie zerowe. - Kazda klasa obiektu COM równiez posiada
jednoznaczny identyfikator klasy (CLSID Class
Identifier), tworzony na tej samej zasadzie co
UUID.
6COMInterfejsy
- W srodowisku CORBA obiekty funkcjonuja w
permanentnie dzialajacych procesach. W srodowisku
COM, odmiennie obiekty maja charakter
tymczasowy. Tworzone sa z chwila gdy klient zada
dostepu do obiektu, gdy zabraknie klientów
odwolujacych sie do obiektu, nastepuje jego
likwidacja. - Czas zycia obiektu COM zarzadzany jest na
zasadzie zliczania odwolan. Klienci powinni
zwiekszac licznik odwolan za kazdym razem, gdy
pobieraja nowe odniesienie do obiektu. Gdy
odniesienie przestaje byc potrzebne, licznik
odwolan powinien byc przez klientów zmniejszany. - Wszystkie obiekty COM realizuja ten sam interfejs
standardowy IUnknown. - Interfejs ten stanowi poczatkowy uchwyt do
obiektu po jego utworzeniu. - Zawiera funkcje AddRef i Release, zarzadzajace
licznikiem odwolan. - Zawiera funkcje QueryInterface, która pozwala
pobrac odniesienie do innego z interfejsów
realizowanych przez obiekt COM.
7COM Przykladowy interfejs IDL
import "unknwn.idl" object, uuid
(7223BBFD-8F42-43e7-92D9-5080991112C7)
interface ISum IUnknown HRESULT Sum(in
int x, in int y, out, retval int retvl)
8COM Implementacja obiektu COM
include "component.h //wygenerowany przez
MIDL zawiera deklaracje interfejsu ISum w
C const CLSID CLSID_MathComp 0xcec2b111,
0xa70f, 0x41ac, 0xab, 0xb9, 0xc, 0x2, 0x43,
0xbe, 0xae,0x49 class CMathComp public ISum
public ULONG __stdcall AddRef() ULONG
__stdcall Release() HRESULT __stdcall
QueryInterface(REFIID riid, void
ppv) HRESULT __stdcall Sum(int x, int y, int
retvl) CMathComp() m_cRef(1) g_cLocks
CMathComp() g_cLocks-- private ULONG
m_cRef
9COM Implementacja obiektu COM
ULONG CMathCompAddRef() return
m_cRef ULONG CMathCompRelease() if (
--m_cRef ! 0 ) return m_cRef delete
this return 0 HRESULT CMathCompQueryInterf
ace(REFIID riid, void ppv) if ( riid
IID_IUnknown ) ppv (IUnknown) this else if
( riid IID_ISum ) ppv (ISum)this else
ppv NULL return E_NOINTERFACE AddRef() re
turn S_OK HRESULT CMathCompSum(int x, int
y, int retvl) retvl x y return S_OK
10COMInterfejsy
11COMFabryki klas
- Dla tworzenia obiektów COM, powloka komponentu
powinna dostarczac tzw. fabryki klas, tj.
specjalnego obiektu COM, który utworzy wlasciwy
obiekt. - Fabryki klas implementuja standardowy interfejs
COM IClassFactory. Glównym elementem tego
interfejsu jest funkcja CreateInstance, której
zadaniem jest stworzenie obiektu.
12COM Implementacja fabryki klas
class CFactory public IClassFactory
public ULONG __stdcall AddRef() ULONG
__stdcall Release() HRESULT __stdcall
QueryInterface(REFIID riid, void
ppv) HRESULT __stdcall CreateInstance(IUnknown
pUnknownOuter, REFIID riid, void
ppv) HRESULT __stdcall LockServer(BOOL
bLock) CFactory() m_cRef(1) g_cLocks
CFactory() g_cLocks-- private ULONG
m_cRef
13COM Implementacja fabryki klas
ULONG CFactoryAddRef() return
m_cRef ULONG CFactoryRelease() if (
--m_cRef ! 0 ) return m_cRef delete
this return 0 HRESULT CFactoryQueryInterfa
ce(REFIID riid, void ppv) if ( riid
IID_IUnknown ) ppv (IUnknown) this else
if ( riid IID_IClassFactory ) ppv
(IClassFactory) this else ppv
NULL return E_NOINTERFACE AddRef() retur
n S_OK
14COM Implementacja fabryki klas
HRESULT CFactoryCreateInstance( IUnknown
pUnknownOuter, REFIID riid, void ppv) if (
pUnknownOuter ) return CLASS_E_NOAGGREGATION
CMathComp pMathComp new CMathComp() if (
!pMathComp ) return E_OUTOFMEMORY HRESULT
hr pMathComp-gtQueryInterface(riid,
ppv) pMathComp-gtRelease() return
hr HRESULT CFactoryLockServer(BOOL bLock)
if ( bLock ) g_cLocks else g_cLocks--
return S_OK
15COMDzialanie klienta
- Klient tworzy obiekty COM, wykorzystujac funkcje
CoCreateInstance. Funkcja ta lokalizuje powloke
komponentu (serwer), pobiera fabryke klas
komponentu i tworzy obiekt COM. - Klient oddzialywuje na obiektach COM a
wykorzystaniem wskazników do interfejsów
implementowanych przez te obiekty, pobieranych z
wykorzystaniem funkcji QueryInterface. - Komponent dba Kazde wywolanie QueryInterface
zwieksza licznik odwolan (dba o to sam obiekt
COM). Jesli klient samodzielnie powiela uchwyt di
obiektu, powinien recznie wywolac AddRef. - Dla kazdego wywolania QueryInterface lub AddRef,
jesli uchwyt do obiektu nie jest juz potrzebny,
klient powinien wywolac Release.
16COM Implementacja klienta
include "component.h" // Wygenerowany Przez
MIDL const CLSID CLSID_MathComp 0xcec2b111,
0xa70f, 0x41ac, 0xab, 0xb9, 0xc, 0x2, 0x43,
0xbe, 0xae, 0x49 void main() IUnknown
pUnknown ISum pSum HRESULT hr
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) i
f ( FAILED(hr) ) coutltlt"Blad CoInitializeEx.
"ltltendl return hr CoCreateInstance(CLSID_M
athComp, NULL, CLSCTX_INPROC_SERVER,
IID_IUnknown, (void) pUnknown) if (
FAILED(hr) ) coutltlt"Blad CoCreateInstance.
"ltltendl return hr pUnknown-gtQueryInterface(
IID_ISum, (void) pSum) if ( FAILED(hr) )
coutltlt"IID_ISum nie jest obslugiwany."ltltendl
return pUnknown-gtRelease() int sum hr
pSum-gtSum(2,3, sum) if ( SUCCEEDED(hr)
) coutltlt"23"ltltsumltltendl pSum-gtRelease() Co
Uninitialize()
17COMRejestr i SCM
- Aby naprawde uaktywnic obiekt, tzn. zapewnic jego
utworzenie i umieszczenie w procesie, skad moze
akceptowac wywolania metod, COM korzysta z
rejestru Windows oraz specjalnego procesu
nazywanego kontrolerem uslug (SCM Service
Control Manager). - Kazdy komponent COM musi zostac zarejestrowany w
kluczu HKEY_CLASSES_ROOT\CLSID pod swoim CLSID.
Opis w rejestrze obejmuje miedzy innymi nazwe
pliku (DLL lub EXE) zawierajacego implementacje
klasy. - Funkcja CoCreateInstance znajduje CLSID
komponentu w rejestrze, konkretyzuje serwer
(powloke) obiektu, tzn. laduje odpowiedni plik
DLL lub uruchamia plik EXE i udostepnia komponent
do obslugi wywolan klienta. - Dla komponentów zdalnych srodowisko COM (a
wlasciwie w tym przypadku DCOM) przekazuje CLSID
obiektu lokalnemu SCM, który w lokalnym rejestrze
odnajduje maszyne serwera, oraz przekazuje CLSID
kontrolerowi SCM na tej maszynie.
18COMOdwolania zdalne
- Dla klienta DCOM kontakt z obiektem
zewnatrzprocesowym (lokalnym lub zdalnym) wyglada
tak samo jak podczas wykonywania obiektów COM
wewnatrzprocesowych we wlasnej przestrzeni
adresowej. - Po konkretyzacji obiektu zdalnego, srodowisko
DCOM przetacza jego interfejs na serwerze i
zwraca klientowi, gdzie jest on przetaczany
odwrotnie do posrednika realizujacego odwolania
do obiektu. - Po udostepnieniu interfejsu klientowi, srodowisko
COM praktycznie nie wykonuje zadnych dodatkowych
operacji. Odwolania do metod obiektu zdalnego
realizowane sa niemalze poprzez natywne wywolania
Windows RPC. - Parametry i wartosci powrotne dla wywolan
obiektów zdalnych musza byc oczywiscie
przetaczane. Standardowy kod przetaczania
generowany jest przez MIDL. Z plików generowanych
przez MIDL nalezy wygenerowac biblioteke DLL i
zarejestrowac w opisie komponentu (tzw.
szeregowanie standardowe). COM oferuje równiez
mozliwosci definiowania przetaczania
niestandardowego.
19COMOdwolania zdalne
20COMOdwolania zdalne
21COMBiblioteki typów
- Biblioteka typów (type library) jest
odpowiednikiem magazynu interfejsów ze standardu
CORBA. Biblioteka typów jest najczesciej
kojarzona z aplikacja lub komponentem skladajacym
sie z róznych obiektów klas. - Kompilowana jest przez MIDL ze specjalnych
deklaracji w opisie interfejsu. Zawiera binarna
wersje interfejsów klasy COM, a takze definiuje
ich metody, parametry i zwracane typy. - Moze byc ona przechowywana w komponencie (jak
inne zasoby) lub w odrebnym pliku. Jesli
komponent ma korzystac z biblioteki typów, musi
byc ona zarejestrowana w jego opisie w rejestrze
Windows. - Biblioteka typów uzywana jest przede wszystkim do
scislego okreslenia sygnatury metody. - Narzedzia programowania korzystaja z bibliotek
typów równiez w celu pomocy w opracowaniu
programu, na przyklad wyswietlajac w wygodnej
postaci interfejsy na ekranie.
22COM Dodanie biblioteki typów do interfejsu
import "unknwn.idl" object,
uuid(10000001-0000-0000-0000-000000000001)
interface ISum IUnknown HRESULT Sum(int
x, int y, out, retval int retval)
uuid(10000003-0000-0000-0000-000000000001),
helpstring("Inside COM Component Type
Library"), version(1.0) library Component
importlib("stdole32.tlb") interface
ISum uuid(10000002-0000-0000-0000-00000000
0001) coclass MathComp
interface ISum
23COM Klient korzystajacy z biblioteki typów
define _WIN32_DCOM //import
"component.tlb" no_namespace //skompil. przez
MIDL biblioteka typow import "component.dll"
no_namespace //jesli biblioteka typow w
komponencie include ltiostream.hgt void
main() CoInitializeEx(NULL,
COINIT_APARTMENTTHREADED) ISumPtr
myRef(__uuidof(MathComp)) int result
myRef-gtSum(5, 13) cout ltlt "5 13 " ltlt
result ltlt endl myRef NULL
CoUninitialize()
24COMAutomatyzacja
- COM umozliwia równiez dynamiczne wywolania metod
obiektów. Obiekty, których zamówienia wywolan
maja byc budowane w fazie wykonania programu,
musza realizowac interfejs standardowy IDispatch.
Interfejs ten podobny jest do interfejsu
dynamicznych wywolan DII w standardzie CORBA. - Obiekty COM realizujace interfejs IDispatch
nazywamy obiektami automatyzacji lub automatyzmu
(automation objects). Moga one realizowac czysty
disp-interfejs, lub udostepniac równiez wlasne
interfejsy niestandardowe. Mówimy wówczas o tzw.
interfejsach dualnych. - W obiektach automatyzacji mozliwe jest równiez
definiowanie wlasnosci. - Metody interfejsu IDispatch korzystaja dla
parametrów ze standardowych typów danych (przede
wszystkim typ VARIANT). Moga wiec byc przetaczane
przy pomocy standardowej biblioteki szeregujacej
i biblioteki typów, niemal bez zadnej dodatkowej
pracy programisty (tzw. szeregowanie z biblioteka
typów).
25COM Interfejs serwera automatyzacji
object, uuid(10000001-0000-0000-0000-00000000000
1), dual interface ISum IDispatch id(1)
HRESULT Sum(in int x, in int y, out, retval
int retvl)
- id(1) jest deklaracja tzw. DISPID,
identyfikatora metody, który wykorzystywany
bedzie do dynamicznego jej wywolania. DISPID moga
miec równiez wlasciwosci. - Musi miec on charakter jednoznaczny (wszystkie
metody i wlasciwosci musza miec rózne
identyfikatory). - Obiekt musi odpowiednio implementowac interfejs
IDispatch, pozwalajacy na wywolanie metody
poprzez podanie jej DISPID oraz zawierajacy
operacje wspomagajace wywolania dynamiczne.
26COM Interfejs IDispatch
interface IDispatch IUnknown // Czy
obslugujesz informacje o typie? HRESULT
GetTypeInfoCount( out UINT pctinfo )
// Zwraca wskaznik do informacji o typie twojego
obiektu. HRESULT GetTypeInfo( in UINT
iTInfo,in LCID lcid, out ITypeInfo
ppTInfo) // Zwraca DISPID metody.
HRESULT GetIDsOfNames( in REFIID riid, in,
size_is(cNames) LPOLESTR rgszNames,
in UINT cNames, in LCID lcid, out,
size_is(cNames) DISPID rgDispId) //
Wywoluje metode. HRESULT Invoke( in
DISPID dispIdMember, in REFIID riid,
in LCID lcid, in WORD wFlags, in,
out DISPPARAMS pDispParams, out VARIANT
pVarResult, out EXCEPINFO pExcepInfo, out
UINT puArgErr)
27COM Implementacja serwera automatyzacji
HRESULT CInsideCOMGetIDsOfNames(REFIID riid,
LPOLESTR rgszNames, UINT cNames, LCID
lcid, DISPID rgDispId) if(riid !
IID_NULL) return DISP_E_UNKNOWNINTERFACE retur
n DispGetIDsOfNames(m_pTypeInfo, rgszNames,
cNames, rgDispId) HRESULT CInsideCOMInvoke(D
ISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS pDispParams,
VARIANT pVarResult, EXCEPINFO pExcepInfo,
UINT puArgErr) if(riid ! IID_NULL) return
DISP_E_UNKNOWNINTERFACE return DispInvoke(this,
m_pTypeInfo, dispIdMember, wFlags,
pDispParams, pVarResult, pExcepInfo,
puArgErr)
- W wiekszosci przypadków funkcje interfejsu
IDispatch implementowane sa z wykorzystaniem
funkcji pomocniczych biblioteki COM,
przeszukujacych biblioteke typów. Mozliwa jest
jednak implementacja niestandardowa.
28COM Dynamiczne wywolanie metody
IDispatch pDispatch OLECHAR name
L"Sum" DISPID dispid pDispatch-gtGetIDsOfNames(
IID_NULL,name,1,GetUserDefaultLCID(),dispid)
VARIANTARG SumArgsPos2 VariantInit(SumArgsP
os0) SumArgsPos0.vt VT_I4 SumArgsPos0.
lVal 7 VariantInit(SumArgsPos1) SumArgsPo
s1.vt VT_I4 SumArgsPos1.lVal
2 VARIANT result VariantInit(result) DISPP
ARAMS Params1 SumArgsPos, NULL, 2, 0
if( FAILED(pDispatch-gtInvoke(dispid,
IID_NULL, GetUserDefaultLCID(),
DISPATCH_METHOD, Params1, result, NULL,
NULL)) ) cout ltlt "pDispatch-gtInvoke()
failed" ltlt endl
29COMPunkty polaczenia
- Podstawowy model komunikacyjny COM opiera sie na
standardowych wywolaniach metod obiektów
zdalnych. W niektórych sytuacjach moze byc on
jednak niewystarczajacy. - Jesli sytuacja wymaga komunikacji dwustronnej,
tzn. aby obiekt poinformowal klienta o zajsciu
pewnego zdarzenia i zazadal jego obsluzenia,
mozliwe jest to dzieki realizacji mechanizmu tzw.
punktów polaczen. - Schemat dzialania jest nastepujacy
- Obiekt definiuje interfejs komunikacyjny, jakiego
wymaga aby przeslac klientowi komunikat o
zdarzeniu. Interfejs ten nazywamy zródlowym
(source interface) lub wychodzacym (outgoing
interface). - Klient, który chce otrzymywac zdarzenia
implementuje wymagany przez obiekt interfejs
zródlowy. Implementacje taka nazywamy ujsciem
(sink). - Obiekt z kolei musi implementowac standardowe
interfejsy COM obslugujace punkty polaczen
(najwazniejszy to interfejs IConnectionPoint).
Interfejs ten zawiera funkcje umozliwiajace
przekazanie obiektowi przez klienta uchwytu do
ujscia (wskaznika do realizacji interfejsu
zródlowego). - Klient po utworzeniu obiektu przekazuje mu
wskaznik do swojego ujscia.
30COMPunkty polaczenia
31COMGrupowe rozsylanie zdarzen
32COMOdbieranie zdarzen od wielu obiektów