Vous êtes sur la page 1sur 304

!

"
"
# $ % &
&'

&
&

( ' ) & *

* &
"

+ " & ,
" "

& ( -)
"
.

.
$ "
.
"
.

"
/ +
.
0123

$ 44%%% 4
$ 54 %4

!" # $ % & ' $ ()


% ) &

8
8 "
&
) $ %

" & "


"

&
& &
& 9 &

. )
. & "
$ "
!" # $

: () "
; $)
% <
=/ 4
8
+5 % $

!" # %&
. /,.&
02 " × :
4 " ' 0=:
0 /> ,?+4

( % <
5
@ $
$ 5
5 $
'
A" $ % " % "
&
* ' * & "

. :24B % ?,(4 * .
:24 % (4+ * . :24
+ ' " %
"
" A"
"
"
&
? #
, (9 ) 9( *
, @ > < ? $ (*,>? , $
- *+/9 ! " , + $ . " ,+.9 &
( * + &(*+ +

+ "
. $ %
$ . '
% ) & ) $ &
" + "

C " & )
$ " + & - "
" "

( =D0=

' ( )*

#
#
% " .4
$

/
6 " 7
%
*

$
' ( ) *
" '

"
" " "
? " )
"
, ) )
%
,
6 7 6 7

# +

) )

( ( ? > 5
# ) 5
+ /
B<
,
( " !
" (
? +
. "
# /
" / + / $
/ ) $

+ ,
!" +

( =D0=

. )

" . BBB
. ) ) .
. )
? $

!" +, , ,
BBB

$
"
%

BBB
# $ $
8
BBB .
" BBB
$ & "
"
" BBB
!" + ,,,

#$$ ! ! %&'
! !

! "!
#$$ ! "! $

! " !

( #$$ ! " ! $ $ !
! " !

( =D0=

,,,
A E 0D 4
A B E 2F
A B E0

.
A

8
?
.

+
- .
$ + & & . &
++* , /
* +
"
' C 3DDD 6 7
3DDDD
3DDDDD
0
$
C "

" G "

!" + .

( =D0=
* "

"
'H & " + .
&
" , 8
. I $ 8.I
" "
"
$ 1 2+ 3 2
!" + / /) *
4 "
"
* 4
#56 4 4
.

? " )
,

? $ $

"
*

!" + / /) *

$ 2
' * 2'*
8 4
?
$
.
$ "
" . )
+ + * "
&) ?
( " &?
" 4 " /
& " $) "
"
" (+
(+ '
"
" "
' .
(- "
"
$ (+
(-

!" + 0

* *
) +

) ( =D0=
*

- ?A)
? "
) ) &9
. ) & B? ?
" 9
) "
!" +0
-

*
"

"

) .
"

+ '
)
# 01:J 5
A

)
"
-
. % $ % )
.

& "
%
* $ %
%

# 8 K 011:
)
/

& ?
012D ! $ + ( $5 #
01J0
/
$ $
& &

* / 8 */8 $ 44%%% 4

"
"
. )
" "
"
A. # A .
# $ 5
(
. .# 'H * / + .
$ % L 'H / +

? 'H / / +
"
"
1 .
7 " "
$ %
"
C
"
" M
C
"
"

2 . )*
; % "

& $ %
" + +
B %
%
& " -
B %

& "
0D/ 0D/
2 . ) *
& "

, "
"
C A C
" A % < " "
"
& <
"

& .
* / )
"

" "
?

! &/
* . .
# .
. $

. ?
"
A B A
- B A $
*# * # $ 5
" !C+ $ 44 %< 4% < 4 N *#
'

&
& $ 4
&
&
#
( &
# &
( " 4 & +

!
- & "

$ $ %
" "

& .
? .)
"

( %
" ;##
I+
3 "
& $

" . &
"
A " %
%
'6 & 7 ?

. 6# 4 5 7 ,8(
) " . %%%
(*,>? ) ) *+/ %%%
8. ? . % ) %%%
B %%% %F
& $ $ % %

, & "
& (
"

( " " "

. "
& "

+ "
)

)
B
" "
&
) .
& ' & "
"
" .

011F ! 5 0 JJ2 DDD 0FD D DD:


0113 ! 5 2 2O= DDD =F 3DD DO
011J ! 5 01 3OD DDD 0 =DF D12 2
0111 ! 5 32 =0: DDD 2 31: 21J 0=
=DD0 ! 5 0=3 ::: 01J F0 =11 31= =3
=DDF ! 5 E=DD DDD DDD O= =1: FJ0 =0
=DD3 ! 5 F3F =:O 0:J 2J 3J0 3:0 01

'
(

.
"
*
(

&A
&
" *
" %
. . "O F= 'H . "2 0=:
"
&A ) &
) " " .
"
2
. &

A M
* " + & &

& A

+ &
9

# & "
B " "
, &
6 7
,

. 9 &A "

? & .
&
)
? "
"
? )
"
"
"
$
? $
)
2
# &
" &

) :
#
1&
#
#

# "
"
#
) "
#

#
"
#
$

2
# L '

? ) /-.
? ? .

-, ) "
.

?
,

+
#( 4. $

(
* & "
"
8

&

5 +
(
#
"

G ' &
)
"

+
& & "

+ $

& &
4
&
+
+
+
+
%

+
.
(

&
? " $ ?A
/ " 9
9
* " )
( "

? P1D . )

* " " )
'H ) " " B
) "
. )
)

1 &
,

&
A "

& "
$
* 0 "

( =D0=
. =DD2 A $ ) . %
. - .8 ./ /&
-
( "
"
& " ) " "
?
.9
& "
"
. & .

.
"

"
"
"

( $
2 &
/
" &
"
&
!

$
2
&

&
#

/
$

&

!
& + ) &

.
* 4 % )

. &

& +
&
,

/ +
4
,
- & ) +
)
.& * 8
# ! " ,+.

(
(

&
!> 2 : + ! (*+L A #
(*,>? 8. ? !?& , / +
- & + * / @
/ +

)
"

. "
*
"

/ + B ;## I+
?$ " +
*?

'

" 5

(
) &
"
? . "
. "
3 # 4 .# &
, $ $
$ " -
;## B
' #
3#

* + # $
* + 3 #$* , (

(
&
&

(
" "
)
- )

,
/
) .
A
. )
+

? "
(
* " . . . .

"
,

+
(

.
" "

"

&
&
"

? &
"
$ &

.
$ &
+ . +
+ . . =
3
,

,
( =D0=

- #
# #

( & "

- " B "
" B " . " &A
. .
-
B )
? " )
;## ) )
( 4 "
& " ≠ " ) &

' ) 6 7 *
* = )

≠ "
8

* =

+ = "
+ &

)
" $
! 0
( =D0=
'
& "
&
"
&
8 "
(
"

+ " +

.
,
"

" " ,

" ,

"
,

( =D0=

B ) "
B B
- +
) &A &? - "
) "
"
.

( =D0=

* $
) (
"
( " "
? "
+
" 1&

A " B " B
;##
B - " B 1&
) )
- " 1& " B )

( "
' 5 -
$ & *222 0 / 2 + ; <
=; .=>) )??@
? O
4 "
" # 2+

" $ '
(
( 4 "
&
(
( ) ?
"
"
(
&
( ? (
(
"
(
&
( )
( )
(
?
&
( )
? (

"
1 3
+
" B "
) " "

$ "
"

/ &

( =D0=

, $
$ "
&
+ ) " .
( 6 7
? $
& 1&
.
1&

.
,

"
$
-
& 8 "
8 " ?
%

( =D0=

"
&
$ ) "

8
" "

"

"
&

( =D0=
( =D0=

8 9
# & "
" . "
( " %

?
" ?" "
" & " "
" "
" " "
? + 37 - 7
+ 7 7 "
" ?

( =D0=
:

( =D0=

&
+ + 4
+ + +
" +
" B ,+. (*,>? 8. ?

'
* . * , + * & ,+)*&
*+/ ( * , @ > < ? $ (*,>?
! " ,+.
( + 8 $ 44 %= 4

( " ! " > !>


+ .
( " (*,>? ( + ((+
) ) ! " + " !+

) (*,>? " "


( ) ! " + " !+
" " B ? $ ?
" / / # <
= # + & 5 $ 44%%% 5 4
# + & ($ $ 44 4 4 $ 4
? > # $ 44%%% 4

+ )? . 8. ? $ 44%%% 4
+ )? !?& $ 44 4
+ &

$ "
&

5
/

+
+
+

+
&
"
?

& ?

&

&
- & )

( & )
&
$

( &

8 &
9

'
( &

&

+
'

. 9

# "
9

'

&
"
"
1

C '"
"

? " "

& "

"

8 &
"
" ($
) "
"
8
&

,
"
($ &
" "
(

- /& /
"0 & / )

? " /
.
" " "

& "
- A#
0

"
&
&

&

4
4
&
#

"
) &

)
. "
$

&
#
"
.

&

*
? "
" &
"
:
& " & ,
" "
& ) " " ;
& ,
& ,
"
& , "
" ; Q
Q
" & , $
" " ( " "
" " &
& )

:
. ) & & "
$
& $
1
&" " R? P
"
&"

? " "
" "
1) L0

" Q
. &
& ' +

&

&
"
& " ' $
0 8 /& C O A F
F:=)OD0 , $ < + $
& &

&

& " )

+
. )

*
& .
0 1 0 1

( =D0=

?
4
&
.
& @
+ .
&
4
.

& 6 7

" "

"
& "
"
(

* +

% )
" "
"
'
8 ) $ $ *$ 5
$
( $ $ $ *$ 5
$
* ($ ? "
" $ $ P
) ? $

, " ) ? P
$ "
? 5 4 $ $ 5 $ " 5
>5 $ 4 5 5
9 5 <

( =D0=

5 '
( < P < $

$ $ "
% %
($ ? P < $ $

( =D0=
& " ?

" & ?

&

"
+ "

+
&

'
( =D0= 1

2 / + 2 /

* #

"
?
"
" "
( "
" " "
.
$

+ "
$

" "

A & )
&

&

'

( =D0=

+
+
"
$
&
'
- ) &
# .
.

"
- "
" &
"

( " "
.
"
) "

'
- )
?
+ &
? "

# $ "
$
# $

-
8
"
.

4 "
Modelul calculului concurent.
Sectiuni critice

Capitolul 2

2015

Rezumat
• Definirea modelului abstract al calculului concurent.
Modelul intreteserii.
• Corectitudine
• Implementarea modelului in Promela/SPIN si Java
• Mecanisme de sincronizare pentru sectiunea critica.
Analiza unor algoritmi de baza.
• Implementarea mecansimelor de sincronizare in
Promela si Java.

2015
Calcul concurent
• = instrument de abstractizare pentru
paralelismul potential.
• = program “clasic” in care instructiunile
masina rezultate in urma compilarii sale sunt executate
secvential de un procesor.
• = executiile proceselor componente se
suprapun in timp.
• = compus din mai multe programe
secventiale care pot fi executate in paralel. Programele
secventiale din cadrul unui program concurent se numesc si
(a nu se confunda cu notiunea de proces dintr&un SO).
• = paralelism potential in care procesele se pot
executa prin partajarea resurselor unui numar restrans
de procesoare.
2015

Exemple de concurenta
• Operatii de intrare – iesire

• Multitasking

• Multiprocesoare si multicalculatoare

• Sisteme distribuite
2015
Operatii de intrare – iesire
• Operatiile de intrare – iesire necesita un timp mult mai indelungat de
desfasurare decat operatiile interne de procesare ce folosesc procesorul si
memoria interna.
– Interfetele om – masina implica activitatea umana care este foarte lenta
– Pot necesita operatii mecanice (fizica mecanica), cum sunt &urile cu &ul
sau folosirea tastaturii
– Pot necesita accesul la dispozitive de memorie externa, cu timpul de acces mai mare
decat timpul intern de procesare

• Se folosesc Procese

ce permit separarea Proces I/E


conceptuala a procesului
de I/E de procesul de Calcul
calcul propriuzis.
Start I/E Sfarsit I/E
• Cele doua procese se pot
Timp
executa concurent.
2015

Multitasking
• &ul este o functie de baza a nucleului SO. Permite
ca executia proceselor sa fie suprapusa “virtual” in timp prin
intermediul (engl. ) unui SO.
• Planificatorul realizeaza (engl. ) si
controleaza executia echitabila (engl. ) a proceselor prin
alocarea periodica a procesorului fiecarui proces din SO.
• Limbajele moderne de programare implementeaza
&ul in cadrul programelor de aplicatie prin
facilitatea de a defini calcule concurente folosind conceptul de
(engl. ) si .
• Programele interactive (cu GUI) trateaza evenimentele
utilizator pe un fir separat ce ruleaza concurent cu firul alocat
programului principal.
2015
Multiprocesoare si multicalculatoare
• Calculatoarele moderne sunt , adica contin mai
multe CPU&uri.
– CPU&urile pot sa fie omogene sau specializate de exemplu pentru
operatii de I/E sau pentru operatii grafice (GPU).
– Un CPU poate contine mai multe unitati de procesare numite si &
uri, in arhitectura .
• Sistemele de calcul moderne sunt , adica sunt
compuse din mai multe calculatoare:
– Retele locale de calculatoare
– e de calculatoare
– Centre de date
– Sisteme distribuite de mari dimensiuni: WWW, P2P, sisteme de
, etc.

2015

Sisteme distribuite
• Sistemele distribuite sunt sisteme multicalculator eterogene ce
comunica prin schimb de mesaje si urmaresc in primul rand
partajarea resurselor:
– Date
– Servicii
– Largime de banda de retea pentru comunicatie
• Accesul la resursele partajate are loc in mod concurent.
• Cresterea performantelor componentelor de deservire (servere)
dintr&un SD poate face apel la arhitecturi multiprocesor sau
multicore, ce necesita folosirea programarii concurente.
• La randul lor, arhitecturile multiprocesor pot folosi intern
comunicarea prin schimb de mesaje, ce face inevitabil apel la
tehnici specifice SD.
2015
Modelul întreŃeserii
• Se numeste o multime
finita de proce secventiale. Procesele sunt
compuse dintr&o multime finita de
.
• (numita si
) este o secventa de
instructiouni atomice rezultata prin
întreŃeserea arbitrara (engl.
) a instructiunilor atomice ale
fiecarui proces compomponent. O executie
(calcul) se numeste si .
• Fiecare proces contine un
, numit si , Sursa: !""#
care indica urmatoarea instructiune ce va fi
executata din procesul respectiv.
Instructiunea respectiva se numeste
(engl. ).
2015

Exemplu de întreŃesere
• Se considera procesele:
= instructiunea p1 urmata de instructiunea p2: p1 → p2
$ = instructiunea q1 urmata de instructiunea q2: q1 → q2
• Scenariile posibile sunt:
p1 → q1 → p2 → q2
p1 → q1 → q2 → p2
p1 → p2 → q1 → q2
q1 → p1 → q2 → p2
q1 → p1 → p2 → q2
q1 → q2 → p1 → q2
• Urmatorul scenariu este ilegal (imposibil):
p2 → p1 → q1 → q2
• Tema: cate scenarii exista daca are pasi si $ are pasi?
2015
Pseudocod concurent
Exemplu trivial de program concurent
integer ←0
p q
integer 1 ← 1 integer 2 ← 2
p1: ← 1 p2: ← 2

Sursa: !""#
• Un algoritm contine:
– Titlul
– Declaratiile de variabile globale
– O multime de coloane, cate o coloana pentru fiecare proces
– Fiecare proces incepe cu declaratii de variabile locale
– Urmeaza instructiunile atomice etichetate ale procesului

2015

Diagrama de stari
• Executia unui program
concurent este definita de p1: ← 1
p2: ← 2
o diagrama cu stari si 1 = 1, 2 = 2
tranzitii intre stari. =0

• Starea include:
– Valorile pointerilor de (end) p1: ← 1
control pentru fiecare p2: ← 2 (end)
proces 1 = 1, 2 = 2 1 = 1, 2 = 2
=1 =2
– Valorile variabilelor globale
si locale din fiecare proces
• Numarul maxim de stari al (end) (end)
unui program concurent (end) (end)
1 = 1, 2 = 2
1 = 1, 2 = 2
creste exponential cu =2 =1
numarul de procese.
Sursa: !""#
2015
Tranzitii de stare
• Fie s1 si s2 doua stari ale unei diagrame de stare a unui
program concurent. Exista o % de la s1 la s2 daca si
numai daca executand una dintre instructiunile unui proces
indicata de pointerul sau de control din s1 ne conduce la
obtinerea starii s2.
• O diagrama de stari se construieste inductiv pornind de la nodul
unic ce reprezinta starea initiala s0 a programului. Se
construiesc tranzitiile posibile din s0 rezultand o multime de
stari de nivel 1. Apoi se construiesc tranzitiile posibile din
starile de nivel 1 rezultand starile de nivel 2, s.a.m.d. Se obtine
in final diagrama de stare ce contine multimea tuturor starilor
ce pot fi atinse (engl. ) pornind din starea initiala.

2015

Scenarii
Procesul p Procesul q 1 2
p1: ← 1 q1: ← 2 0 1 2
(end) q1: ← 2 1 1 2
(end) (end) 2 1 2

Sursa: !""#

• Un scenariu se reprezinta printr&un tabel.


• Coloanele reprezinta procesele si variabilele
• Liniile reprezinta starile.
• Instructiunea executata dintr&o stare se subliniaza.
• Scenariul din exemplu reprezinta calea din partea stanga a
diagramei de stari din slide&ul 12.
2015
Intreteserea in sistemele multitasking

Sursa: !""#

• Exista un procesor si o multime de procese, fiecare avand alocat un


segment de memorie. Starea unui proces (stocata in segmentul de
memorie alocat) contine codul său (inclusiv numaratorul de program),
datele sale (variabilele) si valorile registrelor interne.
• Din cand in cand, se declanseaza intreruperi de la dispozitivele de I/E sau
de la expirarea cuantei de timp. O intrerupere determina comutarea
contextului (engl. & ) adica se schimba procesul din care se va
executa urmatoarea instructiune de catre procesor.
• Intr&o cuanta de timp se executa foarte multe instructiuni, dar momentul
intreruperii este arbitrar, fapt ce justifica intreteserea arbitrara. 2015

Intreteserea in sistemele multiprocesor

Sursa: !""#

• Daca numarul de CPU este cel putin cat numarul de procese, intreteserea
nu mai este necesara.
• O problema sunt (engl. ). Doua
procese incearca sa scrie simultan in aceeasi locatie. Operatiile de scriere
sunt serializate de & a.i. rezultatul sa nu fie inconsistent (adica
daca un proces scrie 1 si celalalt 2 sa nu rezulte o valoare nedeterminata,
de ex. 3). Rezultatul va fi oricum nedeterminist, functie de care proces va
scrie ultimul, in urma intreteserii ce apare pentru evitarea conflictului.
2015
Intreteserea in sistemele distribuite

Sursa: !""#

• Daca fiecare nod executa cate un proces atunci intreteserea nu este


necesara.
• Insa, intr&un SD nu exista ceas global, astfel incat procesele ce ruleaza pe
noduri separate nu se pot coordona decat prin schimb de mesaje. Dpdv
global executiile lor apar ca fiind intretesute in mod arbitrar, datorita
faptului ca nu se poate presupune nici un fel de sincronizare a ceasurilor.
• Totodata, durata unui schimb de mesaje nu poate fi teoretic prezisa, ea
depinzand de topologia SD (tipul grafului, de exemplu inel, complet, …),
incarcarea retelei, etc. 2015

Intretesere arbitrara
• Se poate ignora timpul in analiza programelor concurente.
Astfel, va conta doar ordinea in care sunt executate
instructiunile, nu si momentul de timp cand are loc executia.
• Este posibila construirea de algoritmi care sunt robusti la
modificarea & &ului sau a platformei & .
• Este aproape imposibila repetarea executiei unui program
concurent, asa cum se poate face cu un program secvential, in
scopul depanarii acestuia.

• Concluzie:
%
& &
'
2015
Atomicitatea instructiunilor
Incrementare atomica
integer ←0
p q
p1: ← +1 q1: ← +1

p q p q

p1: ← +1 q1: ← +1 0 p1: ← +1 q1: ← +1 0


(end) q1: ← +1 1 p1: ← +1 (end) 1
(end) (end) 2 (end) (end) 2

Sursa: !""#

• Algoritmul este corect in raport cu postconditia = 2.


2015

Incrementare neatomica

Incrementare neatomica
integer ← 0
p q
integer integer
p1: ← q1: ←
p2: ← +1 q2: ← +1
Sursa: !""#

• Corectitudinea unei analize in presupunerea de intretesere


arbitrara depinde de presupunerea de atomicitate a
instructiunilor – ?
2015
Incorectitudinea incrementarii atomice
p q $
p1: ← q1: ← 0 ? ?
p2: ← +1 q1: ← 0 0 ?
(end) q1: ← 1 0 ?
(end) q2: ← +1 1 0 1
(end) (end) 2 0 1

Sursa: !""#

p q $
p1: ← q1: ← 0 ? ?
p2: ← +1 q1: ← 0 0 ?
p2: ← +1 q2: ← +1 0 0 0
(end) q2: ← +1 1 0 0
(end) (end) 1 0 0
2015

Instructiuni cod masina


• Algoritmul “Incrementare neatomica” poate rezulta in
urma compilarii in limbaj cod masina a algoritmului
“Incrementare atomica”.
• Instructiunile din limbajul de programare sursa sunt
compilate in instructiuni masina (fizica sau virtuala), in
functie de tipul de arhitectura al masinii:
– Masini cu registre generale (de exemplu PDP&11)
– Masini stiva (de exemplu JVM)
• Concluzie:
( )

2015
Incrementare pe masina cu registre generale

Incrementare pe masina cu registre generale


integer ← 0
p q
p1: load R1, q1: load R1,
p2: add R1,#1 q2: add R1,#1
p3: store ,R1 q3: store ,R1
Sursa: !""#

• Tema: De gasit un scenariu pentru care la sfarsitul executiei


acestui algoritm avem ≠ 2.

2015

Incrementare pe masina stiva

Incrementare pe masina stiva


integer ← 0
p q
p1: push q1: push
p2: push #1 q2: push #1
p3: add q3: add
p4: pop q4: pop
Sursa: !""#

• Tema: De gasit un scenariu pentru care la sfarsitul executiei


acestui algoritm avem ≠ 2.
2015
Variabile
Variabile
integer ←0
p q
integer 1, 2 integer Sursa: !""#
p1: ← q1: ← +3
p2: calcul ce nu foloseste
p3: 1 ← ( +1)*2
p4: 2 ← +1
p5: ← 1* 2

• Instructiunea $1 se poate intretese oriunde intre instructiunile lui .


Optimizarea codului (valoarea lui dupa 1 se poate pastra intr&un
registru) poate cauza ca sa nu primeasca cea mai recenta valoare a lui .
• Fortarea stocarii imediate in memorie a valorii lui se poate face
declarand ca fiind variabila .
2015

Corectitudine
• Corectitudinea unui program secvential presupune (i) terminarea
programului si (ii) corectitudinea rezultatului (verificare )
• Corectitudinea unui program concurent presupune verificarea unor
proprietati ale tuturor scenariilor posibile rezultate prin intreteserea
arbitrara:
– Proprietati de (engl. ). O proprietate de siguranta P este satisfacuta
daca si numai daca pentru scenariu posibil si pentru stare ea este
adevarata. Exemplu:
“* ”.
– Proprietati de (engl. ). O proprietate de vivacitate P este satisfacuta
daca si numai daca pentru scenariu posibil o stare in care ea este
adevarata. Exemplu:
“+ % %

2015
Dualitate
• Proprietatile de siguranta se exprima adesea prin sablonul:
“* ”
• Proprietatile de vivacitate se exprima adesea prin sablonul:
“ ”
• + % %
( ) %
• Proprietatile de siguranta si vivacitate sunt duale. Negatia unei proprietati
de siguranta este proprietate de vivacitate si reciproc.
• O proprietate de siguranta se exprima logic prin ∀s ¬P(s), iar o
proprietate de vivacitate se exprima prin ∃s P(s). Negata proprietatii de
siguranta va fi:
¬(∀s ¬P(s)) ≡ ∃s P(s), adica o proprietate de vivacitate. Similar:
¬(∃s P(s)) ≡ ∀s ¬P(s), adica o proprietate de siguranta
• Proprietatile programelor concurente se exprima natural in
.
2015

Echitate
• Exista o singura exceptie a presupunerii ca orice intretesere
arbitrara reprezinta o executie valida a unui progrma concurent.
• Un scenariu este ( ) (eng;. (& ) ) daca
pentru orice stare a sa daca incepand de la ea o instructiune este
activata in mod continuu atunci eventual ea va aparea in
scenariu.
• Sa presupunem ca am executat un scenariu 0, 1, …, si ca
incepand cu , pointerul de control al procesului indica spre
instructiunea ' ce este astfel activata continuu, atunci '
eventual va aparea (va fi selectata) in acest scenariu pentru o
stare , ≥ .
• Observatie: atribuirile si instructiunile de control odata activate,
vor ramane activate in mod continuu.
2015
Oprire in conditii echitabile
Oprire prin iesire din bucla
integer ← 0
boolean ←
p q
p1: while = q1: ←
p2: ←1–
Sursa: !""#

• Proprietatea “* ” este falsa deoarece


se poate construi scenariul infinit: p1, p2, p1, p2, p1, p2, …
• Insa instructiunea q1 a procesului $ este activata in mod continuu. Daca
se accepta doar scenariile echitabile atunci acest scenariu infinit trebuie
sa contina si instructiunea q1. Aceasta instructiune determina ca =
sa fie adevarata, astfel ca se iese din bucla si scenariul se termina.
2015

Instrumente pentru programare concurenta


• Limbaje de programare concurenta
– Ada
– Modula
– Pascal concurent
• Biblioteci si API&uri
– Concurenta din Java
– Concurenta in C#. Modelul este similar cu Java
– Biblioteca de fire POSIX – API standard IEEE
pentru limbajul C
• Instrumente de simulare si verificare
– Limbajul de modelare – Promela
– Instrumentul SPIN de verificare a modelelor
2015
Fire de executie
• Firele de executie (engl. ) permit implementarea unor
fluxuri de control concurent in cadrul aceluiasi proces. Firele
de executie dintr&un proces pot partaja date. Fiecare fir se
caracterizeaza prin propriul numarator de program, stiva si
multime de variabile locale.
• Firele de executie se mai numesc si
(engl. & ). Sistemele de operare
moderne trateaza firele (nu procesele) ca unitati de baza in
operatiile de planficare.
• Deoarece firele unui proces partajeaza spatiul de adrese al
procesului, ele vor avea acces la aceleasi variabile. Acest lucru
ofera suport facil de comunicare prin date partajate. Dar
accesul la datele partajate trebuie realizat cu grija astfel incat sa
nu apara rezultate imprevizibile.
2015

Concurenta in java
• Platforma Java a fost dezvoltata pentru a facilita programarea
concurenta.
• Incepand cu versiunea 5.0 ea include o interfata API de nivel&
inalt pentru concurenta.
• Programarea concurenta presupune folosirea si
. Un proces poate contine unul sau mai multe fire de
executie. De obicei un JVM ruleaza ca un singur proces.
• O facilitate esentiala a platformei Java este
– . Din punctul de vedere al programatorului,
orice aplicatie Java are alocat un proces si ea contine cel putin
un fir numit .

2015
Clasa
• Un fir Java este reprezentat printr&un obiect ' , .

!
" #$ " % #

• Sarcina firului se defineste prin rescrierea metodei .


• Pornirea firului se face cu metoda .
2015

Interfata
• Un fir Java este reprezentat printr&un obiect ce implementeaza
interfata ' - .
& &

#$ " % #

&
!
" " &

• Sarcina firului se defineste tot prin rescrierea metodei .


• Abordarea cu - este mai generala deoarece firul poate
mosteni o alta clasa, - fiind o interfata. 2015
Fire concurente

!
! " '!
% ( ) **
!
" #$ " % # *

% ( ) **
!

# % #

• Tema: sa se ruleze acest algoritm. Ce se observa?


2015

Metoda !
• Metoda ' permite
!
! " '!
unui fir . ce executa
% ( ) ** apelul ! ' () sa se
! suspende pana cand
" #$ " % # * firul ! se termina.
% ( ) **
Apoi . isi continua
! executia.
• In exemplu, firul
principal asteapta ca
toate firele sa se
termine, apoi
afiseaza mesajul
! final si se termina.
" #$

# % #

2015
Incrementare neatomica in Promela
(
% (

*+
% %*+

,
,
,
,*+
% %*+

%
Asteapta ca si $ sa se termine
&& %

Verifica postconditia ==2


2015

Numarare concurenta
Numarare concurenta
integer ←0
p q
integer integer
p1: do 10 times q1: do 10 times
p2: ← q2: ←
p3: ← +1 q3: ← +1

Sursa: !""#

• Ce valori poate avea variabila la sfarsitul executiei


algoritmului de numarare concurenta?
• Tema: sa se implementeze acest algoritm in Promela si Java.
Ce valori poate lua la final?
2015
Definirea problemei sectiunii critice
• Se considera / ≥ 2 procese care executa fiecare cate o bucla infinita.
Corpul buclei cuprinde: (i) si (ii) .
• Cerintele de :
– Excludere mutuala. Instructiunile din sectiunile critice a doua sau mai multe procese
nu pot fi intretesute.
– Lipsa interblocaj (engl. ). Daca anumite procese (procesele) incearca sa
intre in sectiunea lor critica atunci eventual unul dintre ele va reusi.
– Lipsa infometare individuala (engl. ). Orice proces care incearca sa intre in
sectiunea sa critica eventual va reusi.
• Observatie: Lipsa infometarii individuale → lipsa interblocajului
• Cerinta de :
– Accesul la sectiunea critica trebuie sa consume cat mai putin timp si memorie
• Presupuneri:
– Progres in sectiunea critica. Daca un proces intra in sectiunea critica, el va iesi din ea
– Non&progres in sectiunea non&critica. Daca un proces este in sectiunea non&critica el
se poate termina sau se poate bucla la infinit.

2015

Vizualizarea problemei sectiunii critice

2015
Algoritm generic pentru problema sectiunii critice
Algoritm generic pentru problema sectiunii critice
variabile globale
p q

loop forever loop forever

Sursa: !""#

• Problema sectiunii critice se rezolva printr&un % .


Acesta include secvente de instructiuni inainte si dupa sectiunea critica:
– Pre&protocol
– Post&protocol 2015

Prima incercare
Sectiune critica V1
integer ←1
p q
loop forever loop forever
p1: q1:
p2: await =. q2: await =!
p3: q3:
p4: ←2 q4: ←1
Sursa: !""#

• await 〈 〉 este o instructiune de . Daca


〈 〉 este falsa atunci executia procesului ce o contine se blocheaza
pana cand 〈 〉 devine adevarata, prin actiunea altui proces. Altfel
executia procesului ce o contine continua.
2015
Diagrama de stari
• Urmatorul pas al unui algoritm concurent este determinat de
a calculului, ce cuprinde:
– valorile pointerilor de control
– valorile variabilelor globale si locale ale fiecarui proces
• Pentru algoritmul “Sectiune critica V1” starea este data de tripletul 〈
$, 〉.
• Daca algoritmul contine N procese, fiecare proces are instructiuni,
exista M variabile si fiecare variabila ' are ' valori posibile atunci
numarul maxim de stari posibile este:
1× 2×…× /× 1× 2×…×
• Pentru algoritmul nostru acest numar este 4 × 4 × 2 = 32 stari posibile din
care numai 16 pot fi atinse din starea initiala 〈 1, $1, 1〉.
• Numarul de stari se poate reduce la 4 daca se renunta la instructiunile din
sectiunea critica si non&critica, pe baza observatiei ca p1 si p3 se pot
inlocui cu comentarii, iar p1 este totuna cu p2 si p3 este totuna cu p4.
2015

Vizualizarea diagramelor de stari

Sursa: !""#

2015
Corectitudinea primei incercari

• rezulta analizand diagrama de stari


simplificata si observand ca starile 〈p2,q2,1〉 si
〈p2,q2,2〉 nu sunt posibile.

• 0 ' se demonstreaza pe diagrama


simplificata. Fiind simetrica, se considera doar starile
din stanga:
– Din starea 〈p1,q1,2〉 q va intra in sectiunea critica
– Din starea 〈p1,q2,2〉, q fiind in sectiunea critica, va progresa
(conform ipotezei de progres in sectiunea critica) in starea
〈p1,q1,1〉, de unde p va intra in sectiunea critica.
2015

Lipsa infometarii

Sursa: !""#

• Lipsa infometarii se analizeaza pe diagrama initiala. Sa


presupunem ca algoritmul se afla in starea 〈p2,q1,2〉. p doreste
sa intre in sectiunea critica, iar q se afla in sectiunea non&
critica. Conform presupunerii de non&progres in sectiunea non&
critica, nu va putea deveni 1, astfel ca p este infometat.
2015
A doua incercare

Sectiune critica V2
boolean & ← false
boolean & $ ← false
p q
loop forever loop forever
p1: q1:
p2: await & $ = q2: await & =
p3: & ← true q3: & $ ← true
p4: q4:
p5: & ← false q5: & $ ← false

Sursa: !""#

2015

A doua incercare incalca excluderea mutuala

• 4 = p2, 11 = q2, 5 = p3, 12 = q3, 6 =


p5, 13 = q5.
• Starea este 〈 , $,& ,& $〉
• Se obtine secventa de stari 〈4,11,0,0〉 →
〈4,12,0,0〉 → 〈5,12,0,0〉 → 〈5,13,0,1〉 →
〈6,13,1,1〉 unde & = & $ = true.
2015
A treia incercare
Sectiune critica V3
boolean & ← false
boolean & $ ← false
p q
loop forever loop forever
p1: q1:
p2: & ← true q2: & $ ← true
p3: await & $ = false q3: await & = false
p4: q4:
p5: & ← false q5: & $ ← false
Sursa: !""#
• Tema: Sa se arate ca acest algoritm:
– Verifica proprietatea de excludere mutuala
– Incalca proprietatea de interblocare
2015

A patra incercare
Sectiune critica V4
boolean & ← false
boolean & $ ← false
p q
loop forever loop forever
p1: q1:
p2: & ← true q2: & $ ← true
p3: while & $ = true q3: while & = true
p4: & ← false q4: & $ ← false
p5 & ← true q5 & $ ← true
p6: q6:
p7: & ← false q7: & $ ← false

• Tema: Sa se arate ca acest algoritm: Sursa: !""#


– Verifica proprietatea de excludere mutuala
– Verifica proprietatea de interblocare
– Incalca proprietatea de infometare
2015
Algoritmul lui Decker
Algoritmul lui Dekker
boolean & ← false
boolean & $ ← false
interger ←1
p q
loop forever loop forever
p1: q1:
p2: & ← true q2: & $ ← true
p3: while & $ = true q3: while & = true
p4: if =2 q4: if =1
p5: & ← false q5: & $ ← false
p6: await =1 q6: await =2
p7: & ← true q7: & $ ← true
p8: q8:
p9: ←2 q9: ←1
p10: & ← false q10: & $ ← false

Sursa: !""#
2015

Corectitudinea algoritmului lui Dekker

• Tema: Sa se arate ca algoritmul lui Dekker:


– Verifica proprietatea de excludere mutuala
– Verifica proprietatea de interblocare
– Verifica proprietatea de infometare

2015
Instructiuni atomice complexe
• Este dificil de rezolvat problema sectiunii critice folosind doar
instructiuni atomice de incarcare si stocare din/in memorie
(engl. ).
• Instructiunea atomica incarca valoarea unei
variabile booleene si apoi o seteaza la valoarea “true”.
( , ) is:

← true
• Alt exemplu de instructiune atomica este :
( , ) is:
integer


← 2015

Sectiune critica cu " "


Sectiune critica cu test&and&set
boolean ← false
p q
integer integer $
loop forever loop forever
p1: q1:
repeat repeat
p2: test&and&set( , ) q2: test&and&set( , $)
p3: until = false q3: until $ = false
p4: q4:
p5: ← false q5: ← false

Sursa: !""#

• Tema: Sa se arate ca acest algoritm verifica toate cerintele de


corectitudine ale problemei sectiunii critice.
2015
Sectiune critica cu #
Sectiune critica cu exchange
boolean ← true
p q
integer = false integer $ = false
loop forever loop forever
p1: q1:
repeat repeat
p2: exchange( , ) q2: exchange( , $)
p3: until = false q3: until $ = true
p4: q4:
p5: exchange( , ) q5: exchange( , $)

Sursa: !""#

• Tema: Sa se arate ca acest algoritm verifica toate cerintele de


corectitudine ale problemei sectiunii critice.
2015

Alte instructiuni atomice complexe


( , , ) is:

← +

& ( , , &) is:


integer

if =
← &
return

• Tema: Sa se rezolve problema sectiunii critice folosind separat


instructiunile atomice si & .
2015
Instructiuni atomice in Promela
• Toate intructiunile in Promela sunt atomice. Daca se doreste
simularea efectului generarii de cod, trebuie transpus in
Promela exact codul rezultat in urma compilarii.
• Daca se doreste ca o secventa de instructiuni sa fie tratata
atomic (de exemplu pentru implementarea instructiunilor de tip
) se va folosi instructiunea .
(
- -

• Tema: Sa se implementeze sectiunea critica in Promela


folosind instructiuni atomice complexe.
2015

Interfata $ in Java
• Un mecansim de sincronizare se poate implementa folosind
interfata ' 0 in Java.

% . /
/ 00 %
/ 00 %

• Metoda reprezinta codul care se executa inainte de a intra


in sectiunea critica.
• Metoda reprezinta codul care se executa dupa iesirea din
sectiunea critica.
2015
Folosirea interfetei $
• Pentru sincronizare se defineste un obiect ce implementeaza interfata 0 .
Aceasta clasa implementeaza algoritmi
pentru sectiunea critica.
1
(
. / ' ( # ) )

2 3

/ 00

00
* + 00
%
/ 00

• Metoda reprezinta codul care se executa inainte de a intra in sectiunea critica.


• Metoda reprezinta codul care se executa dupa iesirea din sectiunea critica. 2015

Algoritmul lui Dekker in Java


4 / . /
. /5 // . /
! " % 6 %
(
/
Variabile
35
4 +-
" !
" " 4!
% 4
" ! %
" 7
" !

Se foloseste clasa , *+ din Herlihy


/ & Shavit, 2008
35
+-
" ! %
2015
Program de test
. /
% 8
% +(89
% 0
% ! " !
1 " 1
!
35
% ( ) ** ! " 1
% ( ) ** !
% ( ) **
! 4
3 :

#1 ; #* <

% ( ) . / **
. / 2 3

2015

Instructiuni atomice in Java


• Pachetul ' contine o multime de clase
utile pentru implementarea unor variabile cu acces atomic.
• Aceste clase dispun de metode si ce lucreaza similar cu
citirea respectiv scrierea variabilelor definite cu .O
operatie set defineste o relatie de precedenta a executiei fata de
orice operatie ulterioara get asupra unei variabile.
• Spre exemplu, folosind clasa * se poate
implementa un contor cu acces atomic la operatiile de
incrementare / decrementare.
• Tema: Sa se reimplementeze programul prezentat anterior
pentru o multime de fire care realizeaza o operatie de numarare
concurenta, folosind clasa * .
2015
!
"

#

$ ! "
! ! " ! ¬
! "
!

%
& !
∧ # ∨ # ⇒
¬
'
(
' ! ∈
) *⊨ ×
" ∈ ⊨ "
" ∉ ⊨ ≠
⊨ ⊨ ⊨ ∧
⊨ ⊨ ⊨ ∨
⊭ ⊨¬
⊨¬ ∨ ⊨ ⇒
.

, +,
- ← +- ←
. / " +. / "
0 +0
1 ← +1 ←

( ,∧ ,∧¬ ∧¬ 〈
" ,# " ,# " # " 〉
( 0∧ 0
' 2 ¬ 3 0 ∧ 04

) .*
2 # ¬ 3 0 ∧ 04
!
!

!
!
6 ' ∨ 7, ∨ 8 ∨ !# "
" " # 7,# 8# !
! !
& ! ! ) .*
( " . 1⇒
( " ⇒ . 1
( . 1⇔ . 1⇔
( ¬ 3 0 ∧ 04
'
9 # !
& !
0

& . 1" "


# 2
! ,
. 0
: . 1#
!
-
# . 1 # !
1
. 1 # !
¬ 3 0 ∧ 04 0∧ 0

0∧ 0 &
2 0∧ 0
.
. ! 34 0
2 .# 3 4 0 2 .
!
92 .
! . 13 ! 4
# ! 0 # ;

"
# ! 6
:
! #
# #
# : 3 4

2 3 ! # 4
#
: # <
# "$"
3 #4
σ " = ># ,# -# 8?
$ 3 $
4# ) *
# ! #
) *
( % <
⊨ % × #
& σ " = ># ,# -# 8?# !≥>
! σ! !#
σ ! " = !# !7,# !7-# 8?
σ⊨ > ⊨

%
' 3 &#
$ ' 4 @3 4
σ ⊨ !≥> σ !⊨

' ! $
2 # 2 )
.* 2 ¬3 0 ∧ 04
%
' 3 &# '
4 (3 4
σ⊨ 2 !≥> σ ⊨

' !
)
.* 2 3 -⇒ 04 ' -
0 #

%
' 3 4
σ⊨ , - 2 !≥> σ !⊨ - >≤"A!
σ "⊨ ,

! (
1 # #
! 3 4
!
& ' (
' '3 " 4
9
σ⊨ , -
34 2 !≥> σ !⊨ - >≤"A!
σ "⊨ ,

3 4 "≥> σ "⊨ ,

# -
# ! ,

⇔ ∧3 4
⇔ ∨3 4

%
' 3 (4 B
σ⊨ σ,⊨

2 #

, ( ←>
- ( ←,
. ( ←-

. ⇒ 3( " -4
#
# 3( " -4
# <
#
. ⇒ 3( " -4
)
C 2 ' ) *


% #
¬ ⇔ ¬
¬ ⇔ ¬
C 2
⇔ ∨ 3 ∧3 44
⇔ ∨
⇔ ∧



∧ ∨
3 ∧ 4⇔ ∧ 6 ;;

!
& ∧ ⇔ ⃞ ∧ 4
!
)⇒* ∧
!

! # "" 23 #!4 ∧
" ⃞ ∧ 4
# ! ⃞ ∧ 4
)⇐* ⃞ ∧ 4 2 "
" ⃞ ∧ 4 " ∧ #
C ! "

# ∧
**
HH


←,

, +,
- ← +- ←
. /: " +. /: "
0 "- +0 ",
1 ← +1 ←
D / ", +D / "-
E ← +E ←
F +F
G ←- +G ←,
,> ← +,> ←

**
& ! 5 3 ϕ
ϕ4
3 ",∨ " -4 3 4
3 . 1 ∨ F ,> ⇔ 4 3 4
3 . 1 ∨ F ,> ⇔ 4 3 4
¬3 F ∧ F4 3 2 4

# !
& !
3 F ∧ F4 F . F
. ! .
F " !
F #
' %
# ;
& < <
! <
$
$ # '

← (
3 : 4 2 2

) + , +
& ! # ! &
HH
3 F⇒ G4

! 6
3 ,⇒ -4

# ,
)
92 HH # !
#
33 0 ∧ 3 " -44 ⇒ 14

I , " -#
2 G
←, 2 ,#
.# 1;

C ! !
33 0 ∧ 3 " -44 ⇒ 14

& !
⇒ $

! $

# #
#$ #
) **

& 2
)
*
3 -⇒ F4

!
34 # ,
3 4 #
¬ , : ¬ ,

"
! 3 4

#
3 ∧ ",4 ⇒ ¬

! ! -
# - .
! # # 0
! ", # 1
# 1 D
",# D
! ¬ # ¬
& ¬3 3 -⇒ F44 ⃞ -∧¬ F4
2 -∧¬ F
"-
& ! - .
& .# ¬ F# ! # 0
! "-# ! 1
& ! 1 D
! "-# D
! ¬ #
¬
! ! 3 ! 4 D#
G
+,> ", ",# ;
! ! ¬ "-# ",

-∧¬ F ! G 2
←-
, ", C !
, ",
C ! /: . 2
. 0
! ¬ #
! . 0
-
&

% &

3 4
% ( !
!
3 4

&

" ' . )
5 &

5
& !
92 2
$ 2

2
2
2
92 92 2 !
' $ ) 2
$
' 2
J K L
$
$

$
= ?
J K L
2 $
2
$
: !
! 2 #

** ' . )

" ! #

C <
%

&
$

'
)/0
' (
&
! > ' #

& 2 #
#

((

)/0
& -
2 #

# #
&

)*
9 2
# )* '
2 <
' " &
← ># ←>

, +,
- ← 7, +- ← 7,
. / "> ≤ +. / "> A
0 +0
1 ←> +1 ←>
- -

! ! !
!

( #
9
#
-
>
' ! !
&

! #
3 . ≤ # . A
4
/
5
">⇔ ,∨ - 3 4
">⇔ ,∨ - 3 '4
0 ⇒ 3 " >4 ∨ 3 ≤ 4 3 4
0 ⇒ 3 " >4 ∨ 3 A 4 3 4

! # !
&
0
0 # 2 .
3 " >4 ∨ 3 ≤ 4 # ;
0 3 " >4 ∨ 3 ≤ 4
# 3 " >4 ∨ 3 ≤ 4
0# : +- +1 - ≤
1 "> ;

!
!
0 ∧ 0 ⇒ 33 " >4 ∨ 3 ≤ 44 ∧ 33 " >4 ∨ 3 A 44
# 0∧ 0 ' ! ≠>
≠> C !
0∧ 0⇒3 ≤ 4∧3 A 4
3 ≤ 4∧3 A 4 # !
¬3 0 ∧ 04
2 2
"
( 2 3 -⇒ 04
& 2 -⇒ 0
# - ¬ 0
& -# .
¬ 0 . #
. # # 3 ""4
"M> .# . #
2 3 : 4#
C ! ¬33 " >4 ∨ 3 ≤ 44
C ! 3 ≠ >4 ∧ 3 A 4 3 ≠ >4
!
2 - 3 ""4
! 3 ""7,4 "M># ! 3 A 4;

' " & *


N=, *? ' ← =># 8# >?

,
- ' = ? ← , 7 23 ' 4
. : !
0 / 3 ' =!? " >4 3 ' =?≪ ' =!?4
1
D ' =?←>

3 ' =?≪ ' =!?4 ≡ 3 ' =?A ' =!?4 ∨


33 ' =?" ' =!?4 ∧ 3 A !44
%'
2 <

' " &

2
!

( ! #
:

'
' " & *
N=, *? ' ← =># 8# >?
N=, *? # $←= # # ?

,
- # $= ? ←
. ' = ? ← , 7 23 ' 4
0 # $= ? ←
1 : !
D / # $= ? "
E / 3 ' =!? " >4 3 ' =?≪ ' =!?4
F
G ' =?←>
Semafoare si monitoare

Capitolul 4

2015

Rezumat

• Semafoare

• Monitoare

2015
Procese
• Algoritmii pentru sectiuni critice fac apel exclusiv la instructiunile
procesorului gazda.
• Semafoarele definesc o abstractie de programare la un nivel deasupra
instructiunilor masina, de regula la nivelul SO.
• Intr-un sistem multiprocesor sau multitasking mai multe procese pot
partaja resursele aceluiasi procesor.
• Un sistem contine o multime de procese, dintre care:
– Un proces in executie (engl. running)
– Mai multe procese gata de executie (engl. ready)
• O componenta a SO numita planificator (engl. scheduler) realizeaza
periodic realocarea procesorului unui nou proces gata de executie.
• Abstractizand modul de functionare a planificatorului, rezulta ca in
principiu este posibila orice intretesere a proceselor gata de executie.

2015

Stari ale proceselor


• Fiecare proces p are alocata o stare p.state ∈ {inactive, ready, running,
blocked, completed}.
– Initial, dupa creare, procesul se afla in starea inactive
– Apoi procesul este activat si devine gata de executie in starea ready
– Din ready procesul poate trece in executie in starea running
– Din running procesul poate reveni in ready, se poate termina si trece in completed
sau poate inceta executia trecand in blocked.
– Din blocked procesul poate reveni in ready.

inactive ready running completed

blocked
2015
Definirea semafoarelor
• Un semafor S este o structura de date cu doua campuri:
– S.V de tip numar natural
– S.L de tip multime de procese
• Initial semaforul primeste o valoare k ≥ 0 pentru campul S.V si
multimea vida ∅ pentru campul S.L, adica:
semaphore S ← (k, ∅)
• Pentru un semafor S pot fi definite doua operatii atomice:
wait(S)
signal(S)
• Numele date initial de Dijkstra pentru wait si signal sunt P si V.
Ele reprezinta initialele unor cuvinte in limba olandeza:

2015

Operatia wait
wait(S):
if S.V > 0
S.V ← S.V – 1
else
S.L ← S.L ∪ { p }
p.state ← blocked
• Daca S.V > 0 atunci se decrementeaza S.V si procesul curent p
poate continua executia.
• Daca S.V = 0 atunci procesul curent p este adaugat la multimea
S.L si p trece in starea blocked. Se spune ca p devine blocat la
semaforul S.
2015
Operatia signal
signal(S):
if S.L = ∅
S.V ← S.V + 1
else
fie un proces arbitrar q ∈ S.L
S.L ← S.L − { q }
q.state ← ready
• Daca S.L = ∅ atunci se decrementeaza S.V.
• Daca S.V ≠ ∅ atunci se alege un proces arbitrar q ∈ S.L si se
deblocheaza fiind trecut in starea ready.
• Starea procesului p ce executa operatia nu se schimba.
2015

Semafoare generale si binare


• Un semafor care poate lua o valoare reprezentand un numar
natural arbitrar pentru campul S.V se numeste semafor general
sau semafor numarator (engl. counting semaphore)
• Un semafor care poate lua doar una dintre valorile 0 sau 1
pentru campul S.V se numeste semafor binar. Operatia wait(S)
nu se schimba pentru un semafor binar. In schimb, pentru
operatia signal(S), instructiunea de incrementare a campului
S.V se inlocuieste cu S.V ← 1, iar semaforul poate fi initializat
doar cu (0,∅) sau (1,∅).
• Un semafor binar se mai numeste uneori si mutex (uneori
zavoarele folosite in monitoare se numesc mutex, asa ca pot
exista confuzii cu acest termen).
2015
Sectiunea critica cu semafoare pentru 2 procese
Sectiunea critica cu semafoare pentru 2 procese
binary semaphore S ← (1,∅)
p q
loop forever loop forever
p1: sectiune non-critica q1: sectiune non-critica
p2: wait(S) q2: wait(S)
p3: sectiune critica q3: sectiune critica
p4: signal(S) q4: signal(S)

Sursa: M.Ben-Ari, 2006


• Un proces p care doreste sa intre in SC executa wait(S). Daca S.V = 1 atunci S.V devine 0
si p intra in SC. La iesire p executa signal(S) si S.V redevine 1.
• Daca un proces q incearca sa intre in SC in timp ce p este acolo, deoarece S.V = 0, se va
bloca si S va deveni (0,{q}).. Cand p iese din SC, el executa signal(S)..In urma “alegereii
arbirare” din {q}, este ales q, acesta fiind deblocat, putand continua in SC.
2015

Diagrama de stari

In diagrama se elimina liniile


SNC si SC din ambele
procese. Liniile ramase se
redenumesc p1, p2 si q1, q2.

Sursa: M.Ben-Ari, 2006

• Daca q este blocked in q1 atunci singurul proces care va putea avansa este
p. Rezultatul este ca q isi va putea continua executia din q2. Situatia este
similara pentru p.
• Nu exista nici o stare (p2,q2), desi excluderea mutuala este verificata.
• Nu exista o stare in care procesele sunt blocked, deci nu avem interblocaj.
• Daca p executa wait atunci el va progresa direct sau prin intermediul starii
blocked intr-o stare in care poate executa signal, deci nu avem infometare.
2015
Invarianti pentru semafoare
• Teorema: Fie S un semafor, k≥0 valoarea initiala a lui S.V, #signal(S)
numarul de apeluri ale functiei signal(S) si #wait(S) numarul de apeluri
ale functiei wait(S). Atunci sunt valabili urmatorii doi invarianti:
S.V ≥ 0 (Inv1)
S.V = k + #signal(S) – #wait(S) (Inv2)
• Demonstratie:
– Deoarece initial S.V = k, k ≥ 0 si #signal(S) = #wait(S) = 0 rezulta ca Inv1 si Inv2
sunt verificati.
– wait(S) eventual descreste S.V cand S.V > 0, iar signal(S) eventual creste S.V, deci
Inv1 este adevarat in mod trivial.
– Daca se executa wait(S) si S.V este decrementat atunci #wait(S) este incrementat.
– Daca se executa signal(S) si S.V este incrementat atunci #signal(S) este incrementat.
– Daca signal(S) deblocheaza un proces q, atunci se termina executia unui wait(S)
procesul q, astfel ca S.V ramane neschimbat, iar #wait(S) si #signal(S) sunt
imcrementate cu 1.
– Daca wait(S) blocheaza procesul curent atunci S.V, #wait(S) si #signal(S) nu se
schimba.
2015

Excluderea mutuala in sectiunea critica cu semafoare


• Teorema: Implementarea sectiunii critice cu semafoare este
corecta: asigura excluderea mutuala, lipsa interblocajului si
lipsa infometarii.
• Demonstratie:
• Daca #cs e numarul de procese din sectiunea critica atunci
avem invariantul:
#cs + S.V = 1 (Inv3)
• Prin inductie din structura programului rezulta ca:
#cs = #wait(S) – #signal(S)
• Combinand acest invariant cu Inv2 pentru k = 1 rezulta Inv3.
Deoarece conform Inv1 avem S.V ≥ 0 rezulta ca #cs ≤ 1, deci
excluderea mutuala este satisfacuta.

2015
Lipsa infometarii si interblocajului in sectiunea
critica cu semafoare pentru 2 procese
• Daca am avea interblocaj, inseamna ca cele doua procese p si q
ar trebui sa fie blocate in urma executiei apelului wait(S), adica
S.V = 0.
• Deci nici unul dintre cele doua procese nu se afla in SC, adica
#cs = 0. Rezulta ca #cs + S.V = 0, contradictie cu Inv3.
• Daca unul dintre procese, fie el p, ar fi infometat, atunci el va fi
blocat indefinit la semaforul S ce va avea valoarea (0,S.L) cu p
∈ S.L. Conform Inv3, ar rezulta ca #cs = 1 – S.V = 1 – 0 = 1.
Deci obligatoriu celalalt proces q se afla indefinit in SC. Dar in
acest fel se contrazice presupunerea de progres a lui q in SC.

2015

Sectiunea critica cu semafoare pentru N procese


• Algoritmii pentru sectiunea critica cu N procese pentru un N arbitrar
raman identici cu cazul N = 2.
• Se verifica excluderea mutuala si lipsa interblocajului.
• Nu se verifica lipsa infometarii.
# p q r S
1 p1: wait(S) q1: wait(S) r1: wait(S) (1,∅)
2 p2: signal(S) q1: wait(S) r1: wait(S) (0,∅)
3 p2: signal(S) q1: blocked r1: wait(S) (0,{q})
4 p2: signal(S) q1: blocked r1: blocked (0,{q,r})
5 p1: wait(S) q1: blocked r2: signal(S) (0,{q})
6 p1: blocked q1: blocked r2: signal(S) (0,{p,q})
7 p2: signal(S) q1: blocked r1: wait(S) (0,{q})

Liniile 3 si 7 se repeta, p si r “coopereaza” sa-l infometeze pe q.


2015
Asigurarea lipsei infometarii in sectiunea critica cu
semafoare
• Infometarea apare deoarece S.L este o multime din care selectia
procesului pentru deblocare se face in mod arbitrar.
• Daca S.L se implementeaza ca o coada, atunci lipsa infometarii
este asigurata. Fiecarui element din coada ii va veni la un
moment dat randul pentru deblocare.

• Observatie: daca se initializeaza S.V = k > 0 atunci cel mult k


procese se vor afla la un moment dat in SC.

2015

Ordinea executiei cu semafoare


• Se considera un algoritm de calcul in care doua sarcini T1 si T2 pot fi
realizate independent, iar apoi o a treia operatie T va combina rezultatele
operatiilor T1 si T2.
• In mod tipic acest sablon de calcul apare in algoritmii divide et impera,
cum ar fi sortarea prin interclasare.
• Impunerea ordinii corecte de executie, adica T sa astepte dupa ce T1 si
T2 se termina, se poate realiza cu doua semafoare binare S1 si S2.

Ordinea operatiilor cu semafoare


binary semaphore S1 ← (0,∅), S2 ← (0,∅)
p q r
p1: executa operatia T1 q1: executa operatia T2 r1: wait(S1)
p2: signal(S1) q2: signal(S2) r2: wait(S2)
r3: executa operatia T
2015
Semafoare slabe si semafoare tari
• Semafoarele prezentate se numesc si semafoare slabe (engl. weak
semaphores), Motivul este ca nu asigura lipsa infometarii datorita alegerii
arbitrare a procesului care va fi deblocat.
• Se pot defini semafoare tari (engl. strong semaphores) implementand pe
S.L utilizand o coada cu urmatoarele operatii:
– enqueue(Q,x): depune un element x in coada Q si intoarce o noua coada Q’
– dequeue(Q): elimina un element x din coada Q si intoarce (x, Q’) unde Q’ este coada
rezultata prin eliminarea lui x din Q.

wait(S): signal(S):
if S.V > 0 if S.L = ∅
S.V ← S.V – 1 S.V ← S.V + 1
else else
S.L ← enqueue(S.L, p) (q, S.L) ← dequeue(S.L)
p.state ← blocked q.state ← ready
2015

Semafoare busy-wait
• Un semafor busy-wait nu contine componenta S.L iar S.V este identic cu S.
wait(S): signal(S):
await S > 0 S←S+1
S←S–1
• Un semafor busy-wait nu garanteaza lipsa infometarii in problema
sectiunii critice nici pentru cazul a 2 procese. In scenariul de mai jos q
este infometat, linia 4 este identica cu linia 1.
• q e selectat indefinit (echitabil), dar exact cand S = 0, a.i. nu va progresa.

# p q S
1 p1: wait(S) q1: wait(S) 1
2 p2: signal(S) q1: wait(S) 0
3 p2: signal(S) q1: wait(S) 0
4 p1: wait(S) q1: wait(S) 1
2015
Alta definitie a semafoarelor
• Unii autori definesc semafoarele diferit. O metoda combina definitia lui
Dijsktra cu modelul busy waiting. Instructiunea await este inlocuita cu
while, iar un proces ce nu poate avansa este trecut in starea blocked. Apoi,
in signal, dupa incrementarea S.V, se deblocheaza simetric un proces.
• Initializarea are loc ca si in definitia lui Dijsktra.
wait(S): signal(S):
while S.V = 0 S.V ← S.V + 1
S.L ← S.L ∪ { p } if S.L ≠ ∅
p.state ← blocked fie un proces arbitrar q ∈ S.L
S.V ← S.V – 1 S.L ← S.L − { q }
q.state ← ready

• Tema: Sa se demonstreze ca aceste definitii ale operatiilor verifica aceiasi


invarianti ca si in cazul definitiei lui Dijsktra.
2015

Semafoare cu valori negative


• Unii autori permit ca un semafor sa aiba valoarea S.V negativa. Aceasta
valoare se poate folosi pentru a determina, de exemplu, numarul de
elemente aflate in multimea S.L, dupa cum se va vedea mai jos
wait(S): signal(S):
S.V ← S.V – 1 S.V ← S.V + 1
if S.V < 0 if S.V ≤ 0
S.L ← S.L ∪ { p } fie un proces arbitrar q ∈ S.L
p.state ← blocked S.L ← S.L − { q }
q.state ← ready
• Tema: Sa se demonstreze ca aceste definitii ale operatiilor cu semafoare
verifica invariantii urmatori:
(S.V ≤ 0) ⇒ (|S.L| = – S.V)
(S.V ≥ 0) ⇒ (|S.L| = 0)
S.V = k + #signal – #wait – |S.L|
2015
Semafoare in platforma Java
• Platforma Java contine o implementare a semafoarelor in
pachetul de concurenta java.util.concurrent prin clasa
Semaphore.
• Valoarea semaforului se numeste numar de permise.
• Operatiile P si V (wait si signal) se numesc acquire si release.
• Operatia acquire poate genera o exceptie InterruptedException.
• Constructorul clasei contine un parametru suplimentar boolean
utilizat pentru a indica daca semaforul este sau nu echitabil. Un
semafor echitabil corespunde definitiei de semafor tare.

2015

Numarare concurenta cu semafoare I


import java.util.concurrent.Semaphore;
public class CountSem extends Thread {
static volatile int n = 0;
static Semaphore s = new Semaphore(1);
public int getN() {
return n;
}
public void run() {
int temp;
for (int i=0; i<10000000; i++) {
try {
s.acquire();
temp = n;
n = temp+1;
}
catch (InterruptedException e) {}
finally { s.release(); }
}
}
} 2015
Numarare concurenta cu semafoare II
import java.io.*;
public class MainCountSem {
public static void main(String[] args) {
CountSem p = new CountSem();
CountSem q = new CountSem();
p.start();
q.start();
try {
p.join();
q.join();;
}
catch (InterruptedException e) {}
System.out.println("Final counter: "+p.getN());
}
}

2015

Semafoare in Promela
• Tema !

2015
Problema producator - consumator
• Contine doua tipuri de procese:
– Producatori: executa instructiuni ce produc elemente de date, ce
urmeaza a fi trimise la procesele consumator.
– Consumatori: dupa receptionarea unui element de date de la procesele
producator, executa o instructiune ce consuma elementul respectiv
• Problema producator – consumator apare in numeroase situatii
in sistemele de calcul concurente si distribuite:
– Un client Web primeste / trimite date de la / catre nivelul de
comunicatie in retea
– Driver-ul unui dispozitiv de intrare transmite date catre sistemul de
operare
– Un procesor de texte trimite date catre un driver de imprimanta.
Ulterior, driver-ul de imprimanta trimite date catre imprimanta.
– Etc.
2015

Zona tampon in problema producator - consumator


• Comunicarea intre producator si consumator poate fi sincrona
sau asincrona.
• In comunicarea sincrona, producatorul si consumatorul trebuie
sa se coordoneze. Comunicarea nu va avea loc decat atunci
cand ambele procese sunt gata sa schimbe un element de date.
• In comunicarea asincrona, schimbul de informatie are loc
printr-o zona tampon numita buffer. Tamponul are functiile
unei cozi: producatorul depune elemente in spatele cozii, iar
consumatorul preia elemente din fata cozii.
• Exista doua probleme ce necesita atentie:
– Consumatorul nu poate prelua un element dintr-un tampon gol
– Producatorul nu poate depune un element intr-un tampon plin

2015
Producator – consumator cu zona tampon finita
Producator – consumator cu semafoare si zona tampon finita
semaphore notEmpty ← (0,∅)
semaphore notFull ← (N,∅)
finite queue of dataType buffer ← empty queue
p q
dataType d dataType d
loop forever loop forever
p1: d ← produce q1: wait(notEmpty)
p2: wait(notFull) q2: d ← take(buffer)
p3: append(d,buffer) q3: signal(notFull)
p4: signal(notEmpty) q4: consume(d)
• Tema: sa se demonstreze corectitudinea acestui algoritm. Sursa: M.Ben-Ari, 2006

– Nu se extrage un element dintr-un tampon vid


– Nu se depune un element intr-un tampon plin
– Nu exista interblocare 2015

Semafoare divizate
• Algoritmul de rezolvare a problemei producator – consumator cu
semafoare introduce tehnica semafoarelor divizate (engl. split
semaphore).
• El se refera la o tehnica de sincronizare folosind un grup de doua sau mai
multe semafoare ce satisfac un invariant:
“suma lor este (cel mult) egala cu o valoare fixa N”
• In cazul problemei producator – consumator avem invariantul:
notEmpty.V + notFull.V = N
• Tema: sa se demonstreze ca acest invariant este adevarat.
• Daca N = 1 atunci avem un semafor binar cu divizare.
• Observatie: In exluderea mutuala se foloseste un singur semafor binar, iar
instructiunile pereche wait si signal se executa intr-un singur proces.
Pentru sincronizare in problema producator-consumator, o instructiune
wait intr-un proces este imperecheata cu signal in celalalt process.

2015
Problema cinei filosofilor
Cina filosofilor furc4
Fil3
furc3
loop forever
p1: think Fil4 Fil2

p2: preprotocol spaghete

p3: eat furc0 furc2

p4: postprotocol Fil0 Fil1

furc1

• Un filosof poate apuca furculitele numai una cate una si are nevoie de
doua furculite sa poata manca.
• Proprietati de corectitudine:
– Un filosof mananca numai cand are doua furculite
– Excludere mutuala: doi filosofi nu pot detine simultan aceeasi furculita
– Lipsa interblocajului
– Lipsa infometarii
– Comportament eficient in lipsa conflictelor pe furculite 2015

Problema cinei filosofilor – varianta I


Cina filosofilor (varianta I) • Teorema: Nici o furculita nu va fi
Filosof i ( i ∈{0,1,2,3,4} ) detinuta simultan de doi filosofi.
semaphore array[0..4] fork ← • Demonstratie:
[1,1,1,1,1] • Daca #Fi este numarul de filosofi
ce detin furculita i atunci #Fi =
loop forever
#wait(fork[i]) – #signal(fork[i]).
p1: think Din invariantul semaforului
p2: wait(fork[i]) fork[i] rezulta ca fork[i].V = 1 –
p3: wait(fork[i+1]) #Fi de unde #Fi = 1 – fork[i].V.
p4: eat Dar fork[i].V ≥ 0 de unde #Fi ≤ 1.
p5: signal(fork[i])
p6: signal(fork[i+1])

• Este posibil sa apara interblocaj, care va conduce si la infometarea tuturor


filosofilor. Daca fiecare filosof apuca furculita din stanga fork[i] atunci
oricare dintre ei va intra in asteptare pentru furculita din stanga.
2015
Problema cinei filosofilor – variantele II & III & IV
Cina filosofilor (varianta II) • Pentru a asigura lipsa infometarii se
introduce un semafor room care
Filosof i ( i ∈{0,1,2,3,4} )
limiteaza la 4 numarul de filosofi care
semaphore array[0..4] fork ← pot cina la un moment dat.
[1,1,1,1,1] • Teorema: Acest algoritm asigura lipsa
semaphore room ← 4 infometarii filosofilor
loop forever • Demonstratie:
p1: think • Tema !
p2: wait(fork[i]) • Varianta III – este o solutie asimetrica in
p3: wait(room) care primii 4 filosofi sunt identici cu
p4: wait(fork[i+1]) varianta I, iar al 5-lea filosof asteapta
p5: eat intai pentru furculita din dreapta fork[0]
p6: signal(fork[i]) si apoi pentru cea din stanga fork[4].
p7: signal(fork[i+1]) • Varianta IV – filosofii dau cu banul
p8: signal(room) pentru a alege ce furculita asteapta intai.
2015

Definirea monitoarelor
• Monitoarele ofera o alternativa disciplinata si modulara de
implementare a programarii concurente.
• Monitoarele generalizeaza metoda de implementare a
serviciilor nucleului unui SO, pentru a putea fi folosita in
programele concurente de uz general.
• Un monitor asigura excluderea mutuala a apelurilor serviciilor
sale de catre procese diferite. La un moment dat numai un
singur proces poate executa o operatie a monitorului.
• Monitoarele se pot implementa in mod natural folosind obiecte.
Serviciile monitorului se implementeaza ca metode ce asigura
accesul corect la starea (datele) private ale obiectului.

2015
Declararea monitoarelor
Incrementare atomica cu monitoare
monitor CS
integer n ← 0
operation increment
integer temp
temp ← n
n ← temp+1
p q
p1: CS.increment q1: CS.increment Sursa: M.Ben-Ari, 2006

• Monitoarele asigura implicit atomicitatea operatiilor, astfel ca excluderea


mutuala este asigurata in mod corect.
• Un monitor este “static”, el asteptand doar ca operatiile sale sa fie
invocate de procese.
• Fiecare monitor dispune de un zavor (engl. lock) implicit care controleaza
intrarea in monitor. Numai un singur proces poate avea acces la zavor la
un moment dat.
2015

Ilustrarea monitoarelor

monitor CS

n 2

Sursa: M.Ben-Ari, 2006

2015
Variabile conditie
• Un monitor forteaza in mod implicit excluderea mutuala a
accesului la variabilele sale.
• Deseori este nevoie de cerinte explicite de sincronizare. De
exemplu, in problema producator-consumator, producatorul se
va bloca daca tamponul este plin, iar consumatorul se va bloca
daca tamponul este gol.
• Conditiile se pot reprezenta explicit prin declararea de variabile
conditie (engl. condition variable).in cadrul monitorului.
– condition varCond
• Se definesc doua operatii atomice asupra variabilelor conditie:
– waitC(varCond). Aceasta operatie realizeaza blocarea procesului
apelant la variabila conditie varCond
– signalC(varCond). Aceasta operatie realizeaza deblocarea procesului
apelant la variabila conditie varCond
2015

Operatii cu variabile conditie


• O variabila conditie varCond are asociata o coada de procese blocate
varCond.queue.
waitC(varCond): signalC(varCond):
varCond.queue ← if varCond.queue ≠ ∅
enqueue(varCond.queue, p) (q, varCond.queue) ←
p.state ← blocked dequeue(varCond.queue)
release monitor’s lock q.state ← ready
• Procesul p care executa apelul waitC(varCond) este adaugat la coada de
procese blocate, apoi este trecut in starea blocat si se elibereaza zavorul
monitorului in care este definita variabila varCond. Procesul p va elibera
astfel zavorul monitorului, alt proces putand intra in monitor.
• La executia apelului signalC(varCond), daca coada este nevida se extrage
un proces q din coada si se trece in starea ready. Procesul q devine ready,
dar nu exista o cerinta ca procesul ce a executat signalC sa paraseasca
monitorul, el putandu-si continua executia in monitor. 2015
Implementarea semafoarelor cu monitoare
Semafoare cu monitoare
monitor Sem
integer s ← k
condition notZero
operation wait
if s = 0
waitC(notZero)
s←s–1
operation signal Sursa: M.Ben-Ari, 2006
s←s+1
signalC(notZero)
p q
loop forever loop forever
sectiune necritica sectiune necritica
p1: Sem.wait q1: Sem.wait
sectiune critica sectiune critica
p2: Sem.signal q2: Sem.signal
2015

Diagrama de stari pentru problema sectiunii


critice cu semafoare implementate cu monitoare

Sursa: M.Ben-Ari, 2006

2015
Problema producator-consumator cu monitoare
Producator-consumator cu monitoare
monitor PC
bufferType buffer ← empty
condition notEmpty, not Full
operation append(dataType v)
if buffer is full
waitC(notFull)
append(x, buffer)
signalC(notEmpty)
operation take()
dataType w
Sursa: M.Ben-Ari, 2006
if buffer is empty
waitC(notEmpty)
w ← head(buffer)
signalC(notFull)
return w
p q
dataType d dataType d
loop forever loop forever
p1: d ← produce q1: d ← PC.take
p2: PC.append(d) q2: consume(d)
2015

Probleme ale strategiilor de deblocare in monitoare


• Daca p executa signalC si are ca efect trecerea lui q in starea
ready avem situatia urmatoare:
– p poate continua cu urmatoarea instructiune dupa signalC
– q poate continua cu urmatoarea instructiune dupa waitC care generase
blocarea
• Insa monitorul restrictioneaza la un moment dat ca un singur
proces sa execute instructiunile monitorului. Deci fie p, fie q se
vor bloca pana cand celalalt proces elibereaza monitorul.
• Trebuie sa specificam care dintre procesul semnalizator p si
procesul in asteptare q are prioritate sau daca selectia se face
cumva arbitrar.
• Posibil mai exista si alte procese blocate la intrarea in monitor
ce vor trebui luate in considerare intr-o astfel de specificatie. 2015
Ilustrarea unui monitor cu 2 variabile conditie

monitor entry

condition1 waiting

monitor
condition2 waiting

Sursa: M.Ben-Ari, 2006


2015

Stabilirea prioritatilor proceselor blocate in monitoare


• Se introduc notatiile:
– S = prioritatea proceselor semnalizatoare
– W = prioritatea proceselor blocate in asteptare pe variabile conditie
– E – prioritatea proceselor blocate la intrarea in monitor
• Exista 13 posibilitati de stabilire a prioritatilor:
– C32 = 3 cazuri in care doua prioritati sunt egale; fiecare pereche de
prioritati egale poate fi mai mare sau mai mica decat cea de a treia,
deci in total avem 6 = 3 × 2 posibilitati
– 3! = 6 cazuri in care prioritatile sunt diferite
– 1 caz in care cele trei prioritati sunt egale
• Dintre cele 13 cazuri, 7 sunt respinse. Ele apar cand E >
max(S,W). Aceste situatii pot crea infometarea proceselor
semnalizatoare sau a celor in asteptare pe variabile conditie.
2015
Cerinta de reluare imediata – IRR
• Varianta clasica de monitor specifica urmatoarea strategie de
stabilire a ordinii prioritatilor:
E<S<W
• Ea se numeste cerinta de reluare imediata (engl. immediate
resumption requirement – IRR) si a fost introdusa de Tony
Hoare in 1974 sub numele “signal and urgent wait”.
• Efectul este ca un proces aflat in asteptare la o variabila
conditie va fi imediat executat, inaintea procesului semnalizator
si a proceselor blocate la intrarea in monitor.
• Explicatie: procesul semnalizator a modificat starea
monitorului astfel incat conditia este satisfacuta. Procesul in
asteptare executandu-se imediat, va putea presupune ca aceasta
conditie se pastreaza astfel incat isi poate continua operatia.
2015

Lipsa IRR
• Cu ajutorul IRR, asteptarea pe conditie se poate implementa cu urmatorul
sablon, in cadrul unei operatii a unui monitor:
if not condition
waitC(varCond)
• Fara IRR, procesul semnalizator ar putea fi executat inaintea procesului in
asteptare, astfel incat conditia ar putea deveni invalidata inainte ca
procesul aflat in asteptare sa fie deblocat. Din acest motiv, in astfel de
situatii, sablonul de implementare a asteptarii pe variabila conditie este
urmatorul:
while not condition
waitC(varCond)
• Dezavantajul IRR este ca blocheaza procesul semnalizator si astfel
limiteaza concurenta. De aceea se recomanda ca in prezenta IRR, signalC
sa fie ultima instructiune a operatiei procesului semnalizator, astfel incat
dupa executia instructiunii signalC el va parasi monitorul, nemai fiind
nevoie sa fie blocat.
2015
Monitoare in Java
• Fiecare obiect Java are asociat un zavor implicit (engl. intrinsic
lock) care controleaza accesul firelor la obiect. In acest fel orice
obiect Java implementeaza conceptul de monitor.

• Orice fir care doreste sa acceseze (exclusiv) obiectul, trebuie sa


intre in posesia acestui zavor, si sa elibereze zavorul, dupa
terminarea accesului la obiect.

• Intre momentul intrarii in posesie si momentul eliberarii


zavorului se spune ca firul detine zavorul. Cat timp firul detine
zavorul, nici un alt fir nu poate intra in posesia lui pentru a
accesa obiectul. Orice fir ce incearca sa obtina zavorul se va
bloca.
2015

Metode synchonized in Java


• Mecansimul de achizitie/eliberare a unui zavor este
implementat in Java prin:
– introducerea metodelor sincronizate definite prin cuvantul cheie
synchronized si
– definirea unei cozi de fire pentru fiecare zavor implicit. Un fir care
incearca achizitia zavorului va fi blocat si adaugat acestei cozi.
• Un fir incearca sa intre in posesia zavorului implicit al unui
obiect prin executia unei metode sincronizate a obiectului
respectiv. La apelul unei alte metode sincronizate dintr-o
metoda sincronizata, procesul pastreaza zavorul. La terminarea
executiei ultimei invocari a unei metode sincronizate, zavorul
este eliberat.
• O clasa avand toate metodele definite cu synchronized se poate
numi in mod conventional monitor Java.
2015
Variabile conditie in Java
• In Java orice obiect este o variabila conditie. Astfel, clasa de
baza Object dispune de urmatoarele metode:

public final void wait() throws InterruptedException


Determina firul care o executa sa elibereze fortat zavorul si sa fie adaugat
in coada de fire a acestui obiect. Este asemanatoare cu metoda waitC.

public final void notify()


Extrage un fir din coada de fire a obiectului (daca coada nu este vida) si
il trece in starea ready. Este asemanatoare cu metoda signalC.

public final void notifyAll()


Extrage toate firele din coada de fire a obiectului (daca coada nu este
vida) si le trece in starea ready.
2015

Ilustrarea monitoarelor in Java

notifyAll

notify

wait
object

2015
Conventia “wait and notify”
• Executand wait, un fir elibereaza zavorul si este adaugat in lista in
asteptare a obiectului respectiv. Astfel ca un alt proces care era blocat in
asteptarea zavorului va putea accesa obiectul (monitorul).
• Un fir poate executa notify / notifyAll numai daca detine zavorul, si el va
continua sa-l detina dupa executia acestor apeluri. Executia notify /
notifyAll extrage unul / toate firele in asteptare la obiectul respectiv.
• Stretegia IRR determina ca zavorul sa fie transmis imediat de la procesul
semnalizator S la procesul eliberat W. Insa in Java, daca zavorul devine
liber, orice alt proces (inclusiv cele eliberate cu notify / notifyAll) trebuie
sa-l (re-)achizitoneze pentru a (re-)intra in monitor.
• Deci in Java, procesele care doresc sa intre in monitor (E) si cele eliberate
(W) au aceeasi prioritate, in schimb procesul semnalizator (S) retine
zavorul, adica are prioritate mai mare. Deci avem strategia E = W < S,
numita si conventia “wait and notify”, ce a fost propusa de Lampson si
Redell in 1980. 2015

Asteptare pe conditie in Java


• Un proces care a fost deblocat nu poate presupune ca, conditia pe care
astepta este adevarata, el trebuind sa o reverifice intr-o bucla.
• Daca acea conditie este adevarata, el detinand zavorul nici un alt proces
nu o va putea modifica, astfel incat executia poate sa continue.
• Daca acea conditie este falsa, procesul va ceda zavorul si se va bloca din
nou in asteptare ca acea conditie sa devina adevarata.

synchronized void method(...) {


while (! condition) {
try {
wait();
} catch (InterruptedException e) {}
}
// Assume “condition” is true
}
2015
Semnalizare conditie in Java
• Folosirea lui notify va elibera un proces arbitrar din procesele in asteptare
pe un obiect, asa ca este posibila aparitia infometarii !
• Pentru evitarea infometarii se recomanda folosirea algoritmilor de
concurenta din pachetul java.util.concurrency.
• Daca de exemplu un monitor ar fi accesat de procese ce asteapta pe 2
conditii diferite, si am folosi notify pentru eliberarea unui proces cand una
dintre conditii devine adevarata, nu se garanteaza ca va fi eliberat firul
corect. Aceasta deoarece Java nu dispune de variabile conditie in sensul
strict. Intregul obiect va functiona ca o unica variabila conditie pentru
ambele conditii ! Din acest motiv va trebui sa deblocam toate procesele cu
notifyAll, conform schemei urmatoare:
synchronized void method(...) {
// Assume “condition” is true
notifyAll();
}
2015

Blocuri synchronized
• Folosind zavorul implicit asociat unui obiect Java, se poate
implementa facil o sectiune critica sub forma unui bloc
synchronized.
Object obj = new Object();
...
synchronized(obj) {
// sectiune critica
}

• Din pacate, aceasta implementare nu ofera garantia vivacitatii,


deoarece, in prezenta accesului concurent la un astfel de bloc,
un proces arbitrar va primi accesul, fara nici o garantare a
echitabilitatii.

2015
Implementarea semafoarelor cu monitoare in Java
public class MySemaphore {
private int value;
public MySemaphore (int k) {
value = k;
}
synchronized public void P()
throws InterruptedException { Folosirea wait urmeaza
while (value == 0) { schema clasica a asteptarii
wait(); pe conditie fara IRR.
}
--value;
} Daca toate procesele
synchronized public void V() { asteapta pe aceeasi
++value; conditie se poate folosi
notify(); notify.
}
}
2015

Producator – consumator cu monitoare in Java


public class PCMonitor {
final int N = 5; synchronized int take() {
int oldest = 0, newest = 0; int temp;
volatile int count = 0; while (count == 0) {
int buffer[] = new int[N]; try {
synchronized void append(int v) { wait(); // wait not zero
while (count == N) { } catch
try { (InterruptedException e){}
wait(); // wait not full }
} catch temp = buffer[oldest];
(InterruptedException e){} oldest = (oldest + 1) % N;
} count--;
buffer[newest] = v; notifyAll(); // signal not full
newest = (newest + 1) % N; return temp;
count++; }
notifyAll(); // signal not zero }
}

2015
Producator in Java
public class Producator extends Thread {
int q,r,max,min; // min...max, din q in q, incepand cu restul r
PCMonitor buffer;
int c = 0; // Contor de elemente trimise
public Producator(int q,int r,int min,int max,PCMonitor b) {
this.q = q; this.r = r;
this.min = min; this.max = max;
this.buffer = b;
}
int getCounter() { return c; }
public void run() {
int i = min;
while ((i % q) != r) { i++; } // determina primul numar produs
while (i <= max) {
buffer.append(i); c++;
System.out.println("Producer "+r+" produced "+i);
i += q;
}
}
}
2015

Consumator in Java
public class Consumator extends Thread {
int q,r,max,min;
PCMonitor buffer;
int c = 0; // Contor de elemente consumate
public Consumator(int q,int r,int min,int max,PCMonitor b) {
this.q = q; this.r = r;
this.min = min; this.max = max;
this.buffer = b;
}
int getCounter() { return c; }
public void run() {
int i = min,k;
while ((i % q) != r) { i++; }
while (i <= max) {
k = buffer.take(); c++;
System.out.println("Consumer "+r+" consumed "+k);
i += q;
}
}
}
2015
Testare producator – consumator I
public class Main {
static final int NPTHREADS = 10;
static final int NCTHREADS = 5;
static final int MINN = 0;
static final int MAXN = 76;
static Producator pThreads[] = new Producator[NPTHREADS];
static Consumator cThreads[] = new Consumator[NCTHREADS];
static PCMonitor buffer = new PCMonitor();
public static void main(String[] args) {
int i;
System.out.println("Producator - Consumator started");
for (i=0;i<NPTHREADS;i++) {
pThreads[i] =
new Producator(NPTHREADS, i, MINN, MAXN, buffer);
pThreads[i].start();
}

2015

Testare producator – consumator II


for (i=0;i<NCTHREADS;i++) {
cThreads[i] = new Consumator(NCTHREADS, i, MINN, MAXN, buffer);
cThreads[i].start();
}
for (i=0;i<NPTHREADS;i++) {
try { pThreads[i].join(); }
catch(InterruptedException e) {}
}
for (i=0;i<NCTHREADS;i++) {
try { cThreads[i].join(); }
catch(InterruptedException e) {}
}
for (i=0; i<NPTHREADS; i++) {
System.out.println(
"Producator "+i+" produced "+pThreads[i].getCounter()+" elements.");
}
for (i=0; i<NCTHREADS; i++) {
System.out.println(
"Consumator "+i+" consumed "+cThreads[i].getCounter() +" elements.");
}
System.out.println("Producator - Consumator finished");
}
}
2015
Zavoare explicite in Java
• Incepand cu versiunea 1.5, platforma Java a introdus o modalitate de a
defini zavoare explicite.
• Un zavor reprezinta mecanismul de baza ce asigura excluderea mutuala.
Numai un singur fir poate detine zavorul la un moment dat.
• Daca un fir nu poate achzitiona imediat zavorul, atunci:
– Poate incerca in mod continuu obtinerea zavorului (engl. spin), rezultand un zavor cu
filare (engl. spinning lock)
– Se poate bloca (engl. block) rezultand un zavor cu blocare (engl. blocking lock)
• Zavoarele cu filare au sens cand estimam ca timpul de asteptare este mic.
Apelul de blocare al firului poate fi costisitor.
• Zavoarele cu blocare au sens cand estimam ca timpul de asteptare este
mare. Intr-o astfel de situatie un zavor cu filare ar consuma inutil timpul
unui procesor
• Uneori se combina cele doua tehnici: se realizeaza filaj pentru un timp
scurt, iar daca timpul de asteptare este prea mare se recurge la blocare.
2015

Interfata Lock
public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit);
Condition newCondition();
void unlock();
}
• Metoda lock() blocheaza apelantul pana cand achizitioneaza zavorul.
• Metoda lockInterruptibly() este identica cu lock(), dar ridica o exceptie
daca firul este intrerupt in timp ce asteapta.
• Metoda unlock() elibereaza zavorul.
• newCondition() este o metoda factory pentru crearea si returnarea de
obiecte Condition ce reprezinta variabile conditie asociate zavorului.
• Metoda tryLock() achizitioneaza zavorul daca este liber si intoarce imediat
o valoare boolean ce indica daca achizitia a reusit sau nu. Are si o
varianta de apel cu timeout. 2015
Interfata Condition
public interface Condition {
void await() throws InterruptedException;
boolean await(long time, TimeUnit unit)
throws InterruptedException;
boolean awaitUntil(Date deadline) throws InterruptedException;
long awaitNanos(long nanosTimeout) throws InterruptedException;
void awaitUninterruptibly();
void signal(); // wake up one waiting thread
void signalAll(); // wake up all waiting threads
}
• Unui zavor i se pot asocia una sau mai multe variabile conditie create cu
metoda factory newCondition().
• Metodele await(), signal() si signalAll() au roluri similare cu wait(),
notify() si notifyAll() :
– Intrarea in monitor prin metode synchronized se inlocuieste cu apelul metodei lock()
– Iesirea din monitor si eliberarea zavorului se inclocuieste cu metoda unlock()
– Eliberarea explicita a zavorului in monitor se face cu await() pe obiectul Condition.
Astfel un obiect Condition va inlocui variabile Object ce reprezinta monitorul. 2015

Utilizarea obiectelor Condition


Condition conditionProperty = mutex.newCondition();
...
mutex.lock()
try {
while (!property) { // not happy
conditionProperty.await(); // wait for property
}
} catch (InterruptedException e) {
... // application-dependent response
}
... // happy: property must hold
• Se observa ca asteptarea pe conditie utilizeaza acelasi sablon de
programare ca si pentru zavoarele implicite. Diferente:
– Crearea variabilei conditie si asocierea ei cu zavorul
– Apelul explicit pentru achizitia zavorului
– Apelul metodei await() pe obiectul Condition respectiv 2015
Zavoare reentrante
• Utilizand algoritmii prezentati pentru sectiuni critice se pot
implementa diverse clase Lock. Ele au proprietatea ca daca un
fir ce detine zavorul incearca sa-l reachizitioneze atunci el va
crea un interblocaj.
• Un zavor se numeste reentrant daca poate fi achizitionat de mai
multe ori de un acelasi fir.
• Pachetul java.util.concurrent.locks furnizeaza clase pentru
implementarea zavoarelor reentrante.
• O astfel de clasa este ReentrantLock.
• Herlihy & Shavit, 2008 prezinta o metoda de a transforma o
clasa pentru zavoare simple, intr-o clasa pentru zavoare
reentrante.

2015

Tema
1. Sa se implementeze problema filosofilor folosind
monitoare.
2. Sa se implementeze problema producator-consumator
folosind zavoare explicite.
3. Sa se implementeze problema filosofilor folosind
zavoare explicite.

2015
Canale si schimb de mesaje

Capitolul 5

2015

Rezumat

• Modelul comunicatiei prin schimb de mesaje

• Comunicatia intre procese in SD

2015
Comunicatie intre procese
• Procesele pot interschimba informatie prin:
– Memorie comuna
– Comunicare prin transfer de mesaje (engl. message passing)
• Tipuri de comunicare intre procese:
– Comunicatie sincrona: in acest caz schimbul de mesaje este o actiune
atomica ce implica participarea ambelor procese: transmitator sau
expeditor (engl. sender) si receptor sau destinatar (engl. receiver).
• Daca transmitatorul este gata sa transmita un mesaj inainte ca receptorul sa fie
gata sa-l primeasca, transmitatorul se blocheaza.
• Daca receptorul este gata sa primeasca un mesaj, dar transmitatorul nu e gata sa-l
transmita, receptorul se blocheaza
– Comunicatie asincrona: in acest caz transmitatorul nu se va bloca daca
receptorul nu este gata sa primeasca mesajul. In acest caz, mesajul
trebuie salvat temporar pana cand receptorul ajunge in starea de a-l
putea receptiona.
2015

Conventii de adresare
• In general, pentru a putea transmite un mesaj, transmitatorul trebuie sa
cunoasca adresa receptorului.
• Adresare asimetrica. Receptorul nu este obligat sa cunoasca adresa
transmitatorului. Identificarea transmitatorului este posbila, dar
transmitatorul poate optional sa anuleze aceasta optiune. Adresarea
asimetrica este preferata in modelul client-server. Clientul trebuie sa stie
ce serviciu sa apeleze, iar serverul poate fi programat fara sa stie clientii
care il vor apela. Daca e necesar, identitatea unui client se poate incapsula
in mesajele transmise de client serverului.
• Adresare simetrica. Este preferata cand procesele coopereaza pentru
rezolvarea unei probleme, in modelul P2P. Schema se poate implementa
prin definirea unor canale ce pot fi numite (engl. named channels). O
pereche sau grup de procese pot partaja un canal, prin numele acestuia.
• Comunicatie fara adresare. Adresarea se face implicit prin identificarea
unor sabloane in continutul mesajului (engl. pattern matching). Astfel: (i)
rutarea mesajului catre destinatar se poate face functie de continut sau (ii)
mesajul poate fi receptionat de toate procesele.
2015
Producator-consumator cu canale
Producator-consumator cu canale
channel of integer ch
producator consumator
integer x integer y
loop forever loop forever
p1: x ← produce c1: ch ⇒ y
p2: ch ⇐ x c2: consume(y)

Sursa: M.Ben-Ari, 2006


• Un canal conecteaza un proces transmitator cu un proces receptor.
• Un canal are un tip care descrie tipul mesajelor care pot fi transportate de
canalul respectiv.
• Un canal este sincron. In exemplu, transferul de date va avea loc cand
contorul de program al transmitatorului se afla in p2 si al receptorului la
c1. 2015

Problema filosofilor cu canale


forki-1 forki forki+1

Fili-1 Fili
Furci-1 Furci Furci+1

• Furculitele se implementeaza prin procese separate ce comunica prin canale cu


filosofii. Furculitai comunica cu Filosofi prin canalul forksi, in timp ce Filosofi
comunica cu Furculitai prin canalul forksi si cu Furculitai+1 prin canalul forksi+1.
• Fiecare Filosofi asteapta mesaje de la furculitele adiacente Furculitai si
Furculitai+1 pe canalele forksi si forksi+1. Valorile mesajelor nu au importanta, se
vor folosi valori boolene egale cu true. Cand mesajele sosesc, inseamna ca
filosoful foloseste cele doua furculite. Apoi le elibereaza, trimitand cate un
mesaj pe canalele respective.
• Fiecare Furculitai transmite un mesaj prin canalul forksi. Cand acest mesaj este
transmis, furculita este folosita. Apoi asteapta un mesaj pe canalul forksi. Cand
acest mesaj este receptionat, furnculita este eliberata.
2015
Pseudocod pentru problema filosofilor cu canale
Problema filosofilor cu canale
channel of boolean forks[5]
Filosof i Furculita i
boolean dummy boolean dummy
loop forever loop forever
p1: think q1: forks[i] ⇐ true
p2: forks[i] ⇒ dummy q2: forks[i] ⇒ dummy
p3: forks[i+1] ⇒ dummy
p4: eat
p5: forks[i] ⇐ true
p6: forks[i+1] ⇐ true
Sursa: M.Ben-Ari, 2006
2015

Canale in Promela
• Promela permite definirea:
– Canalelor sincrone
– Canalelor asincrone de capacitate fixa
• Mesajele pot fi:
– De un singur tip, sau
– De o secventa de tipuri (de exemplu int urmat de bool)
• Se pot defini vectori de canale.
• Exemplu de canal sincron:
chan ch = [0] of { int }
• Exemplu de vector de canale asincrone:
chan charray[4] = [10] of { int; bool }

2015
Operatii cu canale in Promela
• Receptionarea de valori din canalul ch si stocarea lor in
variabilele vari.
ch ? var1, var2, … varn;
• Testarea unor valori receptionate. Instructiunea este
executabila numai daca componentele primului mesajul din
canal se evalueaza la consti.
ch ? const1, const2, … constn;
• Transmiterea unui mesaj pe un canal.
ch ! expr1, expr2, … exprn;

2015

Procesare concurenta pe flux: problema Conway


• Se considera secventa de caractere primita de la un proces
extern, care trebuie procesata astfel:
– Secvente de 2 ≤ n ≤ 9 caractere consecutive se inlocuiesc prin cifra
corespunzatoare lui n, urmata de caracterul respectiv
– Dupa fiecare k caractere ale acestei transforamri se insereaza un
caracter sfarsit de linie
• Cele doua transformari se vor implementa in doua procese
separate Compress si Output, conectate prin canalul pipe.
• La acestea se adauga procesul Generator care genereaza
secventa de intrare si procesul Printer care afiseaza rezultatul.

inC pipe outC


Generator Compress Output Printer

2015
Problema Conway in Promela: procesul Compress
#include "for.h"
#define K 4
#define MAXN 9
chan inC, pipe, outC = [2] of { byte };
active proctype Compress() {
byte previous, count = 0, c;
Eticheta end ne asigura ca o stare terminala in
inC ? previous;
end:do care serverul este blocat la o instructiune de
:: inC ? c -> receptie nu e considerata invalida
if
:: (c == previous) && (count < MAXN-1) -> count++
:: else ->
if
:: count > 0 ->
pipe ! count+1;
count = 0
:: else
fi;
pipe ! previous;
previous = c;
fi
od
}
2015

Problema Conway in Promela: procesul Output


active proctype Output() {
byte c, count = 0;
end:do
:: pipe ? c;
outC ! c;
count++;
if
:: count >= K ->
outC ! '\n';
count = 0
:: else
fi
od
}
2015
Procesele Generator si Printer
active proctype Generator() {
for (I,1,50)
if
:: inC ! 'a'
:: inC ! 'b'
:: inC ! 'c'
:: inC ! 'd'
fi
rof (I)
}
active proctype Printer() {
byte c;
end:do
:: outC ? c;
if
:: c == '\n' -> printf("\n")
:: (c >= 2) && (c <= 9) -> printf("%d", c)
:: else -> printf("%c", c)
fi;
od
} 2015

Comunicatie sincrona in Java


• Presupune implementarea unei clase Channel<T> care ofera
operatiile send si receive, definite astfel:
– send trimite un mesaj de tip T pe canal. Transmitatorul se blocheaza
pana cand mesajul este receptionat de pe canal de receptor.
void send(T mes)
– receive preia un mesaj de tip T de pe canal. Receptorul se blocheaza
pana cand mesajul este trimis pe canal de transmitator.
T receive()
• Pentru implementare se foloseste sincronizarea pe conditii:
– send instiinteaza receptorii ca un mesaj este ready pe canal, apoi
asteapta ca mesajul sa fie preluat de un receptor (canalul sa redevina
null)
– receive asteapta ca un mesaj sa fie ready pe canal, copiaza mesajul,
elibereaza canalul (acesta va deveni null, iar ready va deveni false) si
instiinteaza potentialii transmitatori ca, canalul este liber.
2015
Implementarea comunicatiei sincrone in Java I
public class Channel<T> {
private T chan = null;
int ready = 0;

public synchronized void send(T mes)


throws InterruptedException {
// Copiaza mesajul pe canal
chan = mes;

// Instiinteaza receptorii potentiali facand


// ready = 1
++ready;
notifyAll();

// Asteapta ca mesajul sa fie preluat de receptor,


// canalul devenind vid
while (chan != null) wait();
} 2015

Implementarea comunicatiei sincrone in Java II

public synchronized T receive()


throws InterruptedException {
// Asteapta ca un mesaj sa fie disponibil pe canal,
// cand ready = 1
while (ready==0) wait();

// Copiaza mesajul local, elibereaza canalul si


// instiinteaza potentialii transmitatori
--ready;
T tmp = chan; chan = null;
notifyAll();
return(tmp);
}
}

2015
Comunicatie asincrona
• In comunicatia asincrona operatia send nu blocheaza transmitatorul pana
la primirea mesajului de catre destinatar. Operatia reuseste imediat, iar
transmitatorul continua fara blocare.
• Mesajele transmise, dar inca nereceptionate sunt stocate temporar intr-o
coada. Expeditorul adauga mesaje la sfarsitul cozii, iar destinatarul preia
mesajele de la inceputul cozii.
• Pentru comunicatia asincrona se
foloseste conceptul de port.
• Un port este reprezentat de o coada
teoretic infinita de mesaje.
• Observatia: un port este similar cu
tamponul din problema producator
- consumator. Tamponul este infinit
dpdv conceptual, deci producatorul
nu mai asteapta ca tamponul sa nu
fie plin inainte de a depune un Sursa: Magee & Kramer, 2006
mesaj. 2015

Comunicatie asincrona in Java


• Se poate implementa dupa modelul producator – consumator.
• Expeditorul este producator.
• Destinatarul este consumator.
• Se va considera ca avem o coada potential infinita. Pentru aceasta se pot
folosi structuri de date predefinite in Java,
public class Port<T> {
Queue<T> queue = new LinkedList<T>();
int ready = 0;
public synchronized void send(T v) {
queue.add(v);
++ready;
notifyAll();
}
public synchronized T receive() throws InterruptedException {
while (ready==0) wait();
--ready;
return queue.remove();
}
}
2015
Rendezvouz
• Conceptul de rendezvouz este un precursor al modelului client-
server din SD.
• Este inspirat din modul in care decurge o intalnire intre doua
persoane:
– Persoanele stabilesc de comun acord un punct de intalnire
– Prima persoana care ajunge la intalnire o asteapta pe cealalta
• Procesele din cadrul modelului rendezvouz au doua roluri:
– Rolul acceptor (engl. accepting). In acest model, locatia de rendevouz
apartine procesului acceptor si se numeste intrare (engl. entry).
– Rolul apelant (engl. calling). El trebuie sa cunoasca atat identitatea
acceptorului, cat si a locatiei de rendevouz.
• Se observa ca rolurile de acceptor si apelant corespund
indeaproape rolurilor de server si client ale modelului client-
server din SD.
2015

Client – server cu rendevouz


Client – server cu rendevouz
Client Server
dataType param, result dataType p, r
loop forever loop forever
p1: param ← ... q1: ...
p2: server.service(param,result) q2: accept service(p, r)
p3: use(result) q3: r ← do service(p)
Sursa: M.Ben-Ari, 2006
La t1 apelantul asteapta
acceptarea apelului.
La t2 se transfera parametrii
de la apelant la acceptor.
La t3 s-a terminat de
executat apelul si se transfera
rezultatul la apelant.
2015
Rendezvouz in Java
• O intrare se reprezinta prin clasa Entry<R,P> ce
implementeaza urmatoarele metode:
– P call(R req) ce primeste ca parametru o cerere req de tip R si intoare
un rezultat de tip P. Aceasta metoda este invocata de procesul apelant.
– R accept() ce intoarce o cerere de tip R. Ea este utilizata de procesul
acceptor si intoarce catre acest proces o cerere primita de la procesul
apelant.
– void reply(P res) ce primeste ca parametru un rezultat de tip P. Metoda
este invocata de procesul apelant si are ca efect transmiterea
(returnarea) raspunsului res catre apelant.
• O intrare incapsuleaza:
– Un obiect care reprezinta un port pentru primirea de mesaj de apel de
la client. Mesajele de apel sunt reprezentate prin clasa CallMsg<R,P>,
astfel ca portul se va reprezenta prin clasa Port<CallMsg<R,P>>.

2015

Protocol cerere-raspuns pentru rendezvouz in Java

Sursa: Magee & Kramer, 2006


2015
Punct de rendezvouz in Java
public class Entry<R,P> {
private CallMsg<R,P> cm;
private Port<CallMsg<R,P>> cp = new Port<CallMsg<R,P>>();

public P call(R req) throws InterruptedException {


Channel<P> clientChan = new Channel<P>();
cp.send(new CallMsg<R,P>(req,clientChan));
return clientChan.receive();
}

public R accept() throws InterruptedException {


cm = cp.receive();
return cm.request;
}

public void reply(P res) throws InterruptedException {


cm.replychan.send(res);
}

private class CallMsg<R1,P1> {


R1 request;
Channel<P1> replychan;
CallMsg(R1 m, Channel<P1> c) {
request = m;
replychan = c;
}
}
} 2015

Apelant de rendezvouz in Java


public class Caller implements Runnable {
private Entry<String,String> entry;
private String id;
public Caller(Entry<String,String> e, String s) {
entry = e; id = s;
}
public void run() {
try {
for (int i=0;i<10;i++) {
System.out.println("Caller "+id+" parameter: "+id);
String result = entry.call(id);
System.out.println("Caller "+id+" result: "+result);
}
}
catch (InterruptedException e){}
}
}
2015
Acceptor de rendezvouz in Java
public class Accepter implements Runnable {
private int c = 0;
private Entry<String,String> entry;
public Accepter(Entry<String,String> e) {
entry = e;
}
public void run() {
try {
while(true) {
String request = entry.accept();
System.out.println("Accepter request"+": "+request);
String result = request+(++c);
System.out.println("Accepter result"+": "+result);
entry.reply(result);
}
} catch (InterruptedException e){}
}
} 2015

Test rendezvouz in Java


public class Main {
static Entry<String,String> e = new Entry<String,String>();
static Caller ionel = new Caller(e,"Ionel");
static Caller gigel = new Caller(e,"Gigel");
static Accepter maria = new Accepter(e);

public static void main(String[] args) {


Thread tIonel = new Thread(ionel);
Thread tGigel = new Thread(gigel);
Thread tMaria = new Thread(maria);

tIonel.start();
tGigel.start();
tMaria.start();
}
}

2015
Rendezvouz folosind clasa Exchanger
• Clasa java.util.concurrent.Exchanger<V> defineste un punct de
rendezvouz unde doua fire pot interschimba doua obiecte.
• Aceasta clasa dispune de metoda:
V exchange(V x)
Apelul asteapta un alt fir sa ajunga la punctul de rendezvouz, ii transfera
obiectul x si apoi ii returneaza un obiect receptionat de la celalalt fir.
• Apelul are si o versiune cu timeout, definita astfel:
V exchange(V x, long timeout, TimeUnit unit)
• Tema: sa se implementeze exemplul cu Ionel, Gigel si Maria folosind
clasa Exchanger. Exchanger

Object 1
Thread 1 Thread 2
Object 2

2015

Receptie selectiva
• Se refera la posibilitatea ca un proces sa astepte intrari nu doar
de pe un singur canal, ci pe o multime de canale:
either cond1 and ch1 ⇒ var1
S1
or cond1 and ch2 ⇒ var2
S2
….
or condn and chn ⇒ varn
Sn
[else Sn+1]
• In acest fel asteptarea are loc “in paralel” pe toate canalele.
Daca este prezenta clauza “else” atunci asteptarea este fara
blocare.
2015
Receptie selectiva in Promela
• Receptia selectiva se poate implementa folosind comenzi cu garzi. In
acest caz, alegerile vor contine si instructiuni de receptionare de pe canale.
• Spre exemplu, se considera o parcare in care sosesc si pleaca masini.
Numarul de locuri libere se reprezinta prin variabila spaces. Pentru
semnalarea sosirilor si plecarilor, procesul Parking primeste mesaje pe
canalele arrivals si departures de la masinile care sosesc sau pleaca.
do
:: (spaces>0) && (arrivals ? car) ->
printf(“Car %d arrived\n”,car); --spaces;
:: (spaces<N) && (departures ? car) ->
printf(“Car %d departed\n”,car); ++spaces;
od
• TODO: Implementarea receptiei selective in Java
2015

Comunicatie intre procese in SD

• Ne referim la nivelul middleware ilustrat cu culoare mai inchisa in figura.


• Se au in vedere UDP si TCP din punctul de vedere al programatorului.
• API-ul UDP furnizeaza o abstractizare a transferului de mesaje (engl.
message passing abstraction). Pachetele independente care contin mesaje
de cerere sau raspuns se numesc datagrame (engl.datagram).
• API-ul TCP ofera o abstractie pentru comunicatia bidirectionala prin
fluxuri (engl.2-way stream). TCP nu delimiteaza mesajele ca UDP.
2015
Comunicatia intre procese in Internet
• Comunicatia intre procese in Internet se bazeaza pe urmatoarea
stiva de protcoale:

• Un programator de aplicatii nu va trebui sa cunoasca in detaliu


nivelele TCP si UDP. In schimb el va utiliza serviciile unui
nivel middleware care ofera un acces facil la aceste nivele.
• Spre exemplu, in platforma Java serviciile acestui nivel
middleware sunt oferite de clasele definite in pachetul java.net.
2015

Fiabilitate si ordonare
• Fiabilitatea presupune garantarea livrarii mesajelor de
la expeditor la destinatar chiar si in prezenta unei
degradari semnificative, dar rezonabile, a numarului de
pachete pierdute din diverse cauze.
• Un serviciu nefiabil nu garanteaza livrarea mesajelor
in situatia in care pachetele de date se pot pierde.
• Integritatea presupune in mod suplimentar ca mesajele
expediate sa ajunge necorupte la destinatar.
• Ordonarea cere ca in anumite aplicatii mesajele sa fie
livrate expeditorului in ordinea expedierii lor de catre
destinatar. Nerespectarea acestei ordini este
considerata un esec.
2015
Destinatia mesajelor
• In Internet destinatia unui mesaj este o pereche (adresa IP, port local).
• Adresa IP reprezinta o adresa a unui calculator gazda conectat la Internet.
Un port local reprezinta destinatia unui mesaj pe un anumit calculator,
reprezentata printr-un numar natural. Un port reprezinta un singur
destinatar, dar poate avea mai multi expeditori.
• Un proces poate receptiona mesaje pe mai multe porturi. Orice proces ce
cunoaste numarul portului asociat unui proces destinatie, ii poate trimite
mesaje. Serverele isi publica porturile pe care primesc mesaje de la clienti.
• Daca un client utilizeaza o adresa fixa de IP pentru a se referi la un
serviciu, atunci acel serviciu va trebui sa ruleze intotdeauna pe acelasi
calculator pentru a ramane valid. Pentru a evita acest lucru, se pot utiliza
urmatoarele tehnici pentru furnizarea transparentei locatiei:
– Programele client se pot referi la servicii prin nume si pot utiliza un server de nume
(engl.name server sau binder) pentru a translata numele in adrese fizice. Aceasta
tehnica permite relocarea serviciilor, dar nu migrarea lor (migrare = mutarea unui
serviciu in timp ce sistemul este in executie), asigurand transparenta locatiei.
2015

Socluri
agreed port
socket any port
socket
message
client server
other ports
Internet address = 138.37.94.248 Internet address = 138.37.88.249

• UDP si TCP folosesc o abstractie numita soclu (engl.socket). Un soclu identifica un


punct terminal de comunicare intre procese. Soclurile au fost introduse pentru prima
oara in Unix BSD. La ora actuala ele exista in majoritatea versiunilor de Unix, in Linux,
in Windows si in MacOS.
• Comunicatia intre procese consta in transmiterea unui mesaj de la un soclu al procesului
expeditor catre un soclu al procesului destinatar.
• Un proces va putea primi mesaje daca dispune de un soclu conectat la un port local si la
adresa de IP a calculatorului pe care el ruleaza. Mesajele trimise la o pereche (adresa IP,
port local) vor putea fi receptionate numai de procesul care dispune de un soclu conectat
la aceasta pereche.
• Un proces nu poate partaja un nume de port cu un alt proces pe acelasi calculator.
Exceptie fac procesele care utilizeaza adresa IP pentru multitransmisie.
2015
UDP si TCP
• TCP – Transport Control
Protocol si UDP – User
datagram Protocol sunt doua
protocoale de transport.
• TCP este un protocol orientat pe
conexiune si fiabil.
• UDP nu este orientat pe
conexiune si nu garanteaza
livrarea fiabila a mesajelor.

2015

Java API pentru adrese IP


• Platforma Java dispune de pachetul java.net pentru reprezentarea
convenabila a obiectelor pentru comunicatia in retele IP:
– Adrese de IP, URL-uri
– Diverse tipuri de socluri
– Reprezentarea pachetelor si mesajelor transmise
– Transmisia respectiv receptia convenabila a mesajelor si pachetelor
– Clase specializate pentru lucrul cu protocolul HTTP: reprezentarea unei conexiuni,
autentificare, cookie-uri, etc
– Exceptiile ce pot apare in aplicatiile ce folosesc comunicatia in retea.
• Reprezentarea unei adrese de IP se poate face prin clasa InetAddress. Din
ea sunt derivate clase pentru adrese IP pe 4 si respectiv 6 octeti:
Inet4Address si Inet6Address.
• Crearea unei adrese de IP se poate face simbolic:
InetAddress unCalculator = Inetaddress.getByName(“software.ucv.ro”);
• Simbolul poate reprezenta si o adresa de IP:
InetAddress unCalculator = Inetaddress.getByName(“127.0.0.1”);

2015
Comunicatia prin mesaje UDP
• http://en.wikipedia.org/wiki/User_Datagram_Protocol
• Definitie: UDP permite transferul de pachete numite
datagrame de la un proces expeditor la un proces destinatar.
Nu exista confirmare si mesajul se poate pierde sau altera
datorita erorilor de transmisie.
• Comunicatia presupune realizarea pasilor:
– Orice proces expeditor sau destinatar va crea intai un soclu legat la o
adresa de IP si un port local.
– Procesul destinatar isi va conecta soclul la un port pe care il va face
cunoscut expeditorilor.
– Expeditorul isi poate lega soclul la orice port local disponibil.
– Expeditorul executa apelul send pentru a transmite un mesaj
destinatarului.
– Apelul receive la destinatar va determina mesajul receptionat cat si
adresa de IP si portul expeditorului. Se permite astfel trimiterea
explicita a unui raspuns expeditorului. 2015

Caracteristici ale comunicatiei prin mesaje UDP


• Dimensiunea mesajelor. Protocolul IP permite transmiterea de pachete de
pana la 216 octeti (IPv4, incluzand si antetele !). Dimensiunea uzuala a
mesajelor este de 8 Kocteti. Se determina in functie de aplicatie.
• Blocarea. Comunicatia prin datagrame UDP foloseste operatii send fara
blocare si operatii receive cu blocare. Daca nu exista procese la destinatie
cu un soclu conectat corespunzator, mesajele se pierd. Daca procesul
destinatar are de efectuat alte sarcini, el poate folosi un fir separat pentru
realizarea acestor sarcini.
• Timeout. Uneori nu este posibil ca destinatarul sa astepte nelimitat
primirea unui mesaj. In acest caz se poate seta un timeout pentru un soclu
specificat.
• Receptie de la oricine. Metoda receive nu specifica o adresa pentru
originea mesajelor – cu alte cuvinte receptia poate veni de la oricine
cunoaste adresa si portul destinatarului. Este insa posibil sa se conecteze
un soclu pentru datagrame cu un port si o adresa de IP la distanta astfel
incat comunicatia sa se faca doar cu adresa respectiva.
2015
Modelul de eroare si utilizari ale UDP
• Modelul de eroare. O comunicatie fiabila e caracterizata de integritate si
validitate: mesajele sa nu fie corupte, duplicate, respectiv sa nu se piarda.
• In UDP mesajele se pot pierde fie la transmisie, fie la receptie si uneori
pot fi transmise intr-o ordine eronata.
– Erorile de omisiune se pot inlatura prin introducerea unor mesaje de confirmare.
– Asigurarea ordinii corecte se poate face printr-un nivel suplimentar si prin gestiunea
explicita a ordinii de livrare/receptie a mesajelor.
• Exemple de aplicatii ce pot folosi UDP:
– Serviciul de DNS, serviciul DHCP (Dynamic Host Configuration Protocol)
– Un server de timp care furnizeaza clientilor valoarea timpului curent
– Comanda ping pentru testarea comunicatiei intre doua programe in retea
– SNMP (Standard Network Management Protocol)
– VOIP (Voice Over IP)
• Avantajul UDP este ca evita supraincarcarea necesara garantarii unei
comunicatii fiabile, specifica TCP. O aplicatie isi va implementa propriile
mecanisme de asigurare a unei comunicatii fiabile, atat cat este necesar.
2015

Java API pentru comunicatie UDP – DatagramPacket


• Clasa DatagramPacket. Aceasta clasa furnizeaza un constructor pentru
un mesaj UDP de expediat format dintr-un vector de octeti, lungimea
mesajului, si o pereche (adresa IP, numar port) corespunzatoare unui
soclu destinatie:
DatagramPacket(byte[] buf, int length, InetAddress
address, int port)
• Clasa dispune de un alt constructor pentru receptionarea unui mesaj
UDP:
DatagramPacket(byte[] buf, int length)
• Mesajul se determina cu getData, iar portul si adresa expeditorului cu
getPort si getAddress.
• Obiectele acestei clase pot fi transmise cu primitiva send si sunt
preluate si returnate de catre primitiva receive a clasei
DatagramSocket.

2015
Java API pentru comunicatie UDP – DatagramSocket
• Clasa DatagramSocket implementeaza socluri pentru expedierea si
receptionarea de datagrame UDP.
• Furnizeaza un constructor ce primeste un port, cat si un constructor fara
parametrii care permite sistemului sa aleaga un port liber.
public DatagramSocket() throws SocketException
public DatagramSocket(int port) throws SocketException
• Clasa DatagramSocket furnizeaza metode ce permit urmatoarele:
– Expedierea si receptia de mesaje cu send si receive. send primeste un obiect
DatagramPacket ce contine mesajul si destinatia sa. receive primeste un obiect
DatagramPacket cu mesaj vid pentru receptionarea unui nou mesaj.
public void send(DatagramPacket p) throws IOException
public void receive(DatagramPacket p) throws IOException
• Alte metode:
– setSoTimeout pentru setarea unui timeout. Astfel metoda receive se va bloca pentru
timpul specificat. Daca timpul expira se va genera exceptie
SocketTimeoutException.
– Conectarea la un anumit port si adresa IP la distanta cu connect. In acest fel soclul
se va utiliza doar pentru comunicatia cu adresa respectiva. 2015

Client UDP
import java.net.*;
import java.io.*;
public class UDPClient {
args[0] este mesajul
public static void main(String args[]) {
DatagramSocket aSocket = null;
args[1] este numele serverului
try {
aSocket = new DatagramSocket();
byte [] m = args[0].getBytes(); // Conversie mesaj in sir de octeti.
InetAddress aHost = InetAddress.getByName(args[1]); // Get hostname.
int serverPort = 6789;
Creare soclu si expediere mesaj
DatagramPacket request =
new DatagramPacket(m, args[0].length(), aHost, serverPort);
aSocket.send(request);
byte[] buffer = new byte[1000];
Receptioneaza ecoul mesajului
DatagramPacket reply = new DatagramPacket(buffer, buffer.length);
aSocket.receive(reply);
System.out.println("Reply: " +
new String(reply.getData(),0,reply.getLength()))
} catch (SocketException e)
{System.out.println("Socket: "+e.getMessage());
} catch (IOException e) {System.out.println("IO: " + e.getMessage());
} finally {if (aSocket != null) aSocket.close();}
}
} 2015
Server UDP
import java.net.*;
import java.io.*;
public class UDPServer{
public static void main(String args[]){
DatagramSocket aSocket = null;
try {
aSocket = new DatagramSocket(6789); Legarea soclului la portul 6789 al serverului
byte[] buffer = new byte[1000];
while (true) { Receptionare mesaj
DatagramPacket request = new DatagramPacket(buffer, buffer.length);
aSocket.receive(request);
DatagramPacket reply =
new DatagramPacket(request.getData(), request.getLength(),
request.getAddress(),request.getPort());
aSocket.send(reply); Expediaza mesajul in ecou
}
} catch
(SocketException e){System.out.println("Socket: " + e.getMessage());
} catch (IOException e) {System.out.println("IO: " + e.getMessage());
} finally {if(aSocket != null) aSocket.close();}
}
} 2015

Comunicatia prin fluxuri TCP


• http://en.wikipedia.org/wiki/Transmission_Control_Protocol
• Comunicatia este abstractizata prin crearea unui flux virtual si sigur de octeti intre
procesul expeditor si procesul destinatar.
• Dimensiunea mesajelor:
– Aplicatia este cea care alege dimensiunea datelor scrise sau citite din flux.
• Mesajele pierdute. TCP utilizeaza intern mesaje de confirmare. De exemplu, pentru
fiecare pachet IP trimis se asteapta o confirmare de primire. TCP foloseste o schema
bazata pe o fereastra alunecatoare pentru a limita numarul de confirmari necesare.
• Controlul fluxului. TCP incearca sa se adapteze la vitezele actuale de transmisie sau
receptie ale proceselor implicate. De exemplu, daca expeditorul este mai rapid decat
destinatarul, el va fi blocat pana cand destinatarul poate receptiona din nou.
• Ordonarea si duplicarea mesajelor. Se asociaza identificatori de mesaje pentru fiecare
pachet IP, fapt ce permite destinatarului sa detecteze si sa rejecteze duplicatele, sau sa
reordoneze pachetele ce nu au fost receptionate in ordinea in care au fost trimise.
• Destinatia mesajelor. Comunicatia este bazata pe conceptul de conexiune. Perechea de
procese comunicante stabileste intai o conexiune inainte de a comunica pe flux.
Conexiunea furnizeaza fluxurile care vor fi citite respectiv scrise, nefiind nevoie de a
indica de fiecare data adresele de IP si numarul portului. Stabilirea conexiunii presupune
executarea unui apel connect de la expeditor, urmat de un apel accept la destinatar.
2015
Probleme ale comunicatiei prin fluxuri TCP
• API pentru comunicatia pe flux presupune ca procesele care comunica au
roluri de server, respectiv client, pe parcursul stabilirii conexiunii.
• Rolul client presupune crearea unui soclu legat la orice port disponibil si
apoi executarea unui apel connect de cerere a unei conexiuni catre un
proces server, pe un anumit port public al serverului.
• Rolul server presupune crearea unui soclu de ascultare legat la un port al
serverului si asteptarea cererilor de conexiune de la clienti. Soclul de
ascultare mentine o coada de cereri de conexiune. Cand soseste o noua
cerere, se creaza un nou soclu pe server pentru comunicatia cu clientul.
Soclul de ascultare e mentinut pentru tratarea de noi cereri.
• Fiecare dintre cele doua socluri dispune de cate o pereche de fluxuri.
Expedierea / receptia se realizeaza prin scrierea / citirea din cele 2 fluxuri.
• Blocare. Cand un proces vrea sa citeasca date din fluxul de intrare se
poate bloca pana cand datele devin disponibile. Expeditorul se poate bloca
de catre mecanismul TCP daca trimite cu o viteza prea mare.
• Fire. Cand un server accepta o noua conexiune el va crea un nou fir pentru
gestionarea comunicatiei cu clientul. 2015

Modelul de eroare si utilizari ale TCP


• Pentru a satisface proprietatea de integritate a unui canal sigur, TCP
foloseste sume de control pentru a detecta mesajele corupte si numere de
secventa pentru a realiza ordonarea corecta a mesajelor si a rejecta
pachetele duplicate.
• Daca pierderea de pachete depaseste o limita maxima admisibila sau daca
reteaua atinge limite neacceptabile de congestie, software-ul TCP este
responsabil cu intreruperea conexiunii. La intreruperea unei conexiuni,
procesele implicate vor fi informate in mod corespunzator atunci cand vor
incerca sa o foloseasca. Efectul unei astfel de informari este insa ca
procesele nu vor putea distinge intre o eroare a retelei sau o eroare in
procesul de la celalalt capat al conexiunii si nu vor sti daca mesajele
recent transmise au fost sau nu livrate corect.
• Foarte multe dintre serviciile Internet ruleaza peste TCP:
– HTTP, protocolul pentru comunicatia intre clientii si serverele de Web
– FTP, protocolul pentru transfer de fisiere
– Telnet, protocolul de acces la un sistem folosind un terminal aflat la distanta.
– SMTP, protocolul pentru transferul postei electronice.
2015
Java API pentru comunicatie TCP - I
• Clasa ServerSocket. Este utilizata de server pentru a crea un soclu de
ascultare pe portul serverului. Metoda accept preia o cerere de conexiune
de la un client din coada de cereri primite. Daca coada este vida atunci se
blocheaza procesul server pana la aparitia unei conexiuni.
public class ServerSocket {
// Creaza un soclu server nelegat la nici un port
ServerSocket();
// Creaza un soclu server legat la "port"
ServerSocket(int port);
// Apare in plus dimensiunea maxima
// a cozii de cereri "backlog"
ServerSocket(int port, int backlog);
// Asteapta o conexiune cu blocare
public Socket accept();
// Inchide soclul
public void close();
...
}
2015

Java API pentru comunicatie TCP - II


• Clasa Socket se utilizeaza de catre o pereche de procese implicate intr-o conexiune.
Clientul va crea un obiect Socket specificand numele si portul serverului. Constructorul
realizeaza automat si conectarea la server.
public class Socket {
// Creaza un soclu neconectat
public Socket();
// Creaza un soclu pentru comunicare pe flux legat la "port“ si adresa
// de IP "address"
public Socket(InetAddress address, int port);
// Se specifica in plus adresa de IP locala "localAddr" si portul
// local "localPort"
public Socket(InetAddress address,int port,
InetAddress localAddr,int localPort);
// Creaza un soclu. Gazda unde se conecteaza se indica prin nume "host"
public Socket(String host,int port);
// Determina fluxul de intrare asociat soclului
public InputStream getInputStream();
// Determina fluxul de iesire asociat soclului
public OutputStream getOutputStream();
...
}
2015
Client TCP - I
import java.net.*;
args[0] este mesajul
import java.io.*; args[1] este numele serverului
public class TCPClient {
public static void main(String args[]) {
Socket s = null; Crearea soclului si legarea sa la portul 6789 al serverului
try {
int serverPort = 6789;
s = new Socket(args[1], serverPort);
DataInputStream in = Creare fluxuri de I si E
new DataInputStream(s.getInputStream());
DataOutputStream out =
new DataOutputStream(s.getOutputStream());
out.writeUTF(args[0]); // UTF is a string encoding.
String data =
Expediere si receptionare mesaj folosind fluxurile
in.readUTF();
System.out.println("Received: "+ data) ;
}
2015

Client TCP - II
} catch (UnknownHostException e) {
System.out.println("Socket:"+e.getMessage());
} catch (EOFException e) {
System.out.println("EOF:"+e.getMessage());
} catch (IOException e) {
System.out.println("readline:"+e.getMessage());
} finally {
if (s != null)
try {
s.close();
} catch (IOException e) {
System.out.println("close:"+e.getMessage());
}
}
}
}

2015
Server TCP. Acceptarea unei conexiuni
import java.net.*;
import java.io.*;
public class TCPServer {
public static void main (String args[]) {
try {
int serverPort = 6789; Legarea soclului la portul 6789 al serverului
ServerSocket listenSocket =
new ServerSocket(serverPort);
while (true) { Serverul asteapta cereri de conexiune
Socket clientSocket = listenSocket.accept();
Connection c = new Connection(clientSocket);
} Pentru fiecare cerere de conexiune serverul creaza
} catch(IOException e) { un fir responsabil cu tratarea conexiunii.
System.out.println("Listen socket:"+e.getMessage());
}
}
}
2015

Server TCP. Tratarea unei conexiuni - I


class Connection extends Thread {
DataInputStream in;
DataOutputStream out;
Socket clientSocket;
public Connection(Socket aClientSocket) {
try {
clientSocket = aClientSocket;
Creare fluxuri de I si E
in =
new DataInputStream(clientSocket.getInputStream());
out =
new DataOutputStream(clientSocket.getOutputStream());
this.start();
} catch(IOException e)
System.out.println("Connection:"+e.getMessage());
}
}

2015
Server TCP. Tratarea unei conexiuni - II
public void run() {
try { // An echo server.
String data =
Firul citeste un mesaj din fluxul de intrare si
in.readUTF();
il scrie in ecou in fluxul de iesire
out.writeUTF(data);
} catch (EOFException e) {
System.out.println("EOF:"+e.getMessage());
} catch(IOException e) {
System.out.println("readline:"+e.getMessage());
} finally {
try {
clientSocket.close();
}
catch(IOException e) { /* close failed */ }
}
}
}
2015

Comunicatie de grup - concept


• Schimbul unu-la-unu de mesaje in perechi de procese nu e cel
mai bun mod de comunicare intre un proces si un grup.
• Un exemplu este un serviciu distribuit implementat sub forma
unui grup de procese pentru toleranta la defecte sau pentru
cresterea disponibilitatii.
• Se numeste operatie de trimitere multipla (engl. multicast) o
operatie de trimitere a unui mesaj de la un proces catre fiecare
membru al unei multimi de procese astfel incat apartenenta la
grup sa fie transparenta pentru procesul expeditor.
• Trimiterea multipla nu trebuie confundata cu difuzarea (engl.
broadcast) in retea. Aceasta operatie presupune trimiterea de
mesaje tuturor statiilor dintr-o retea. In IPv4 exista o metoda
de a determina adresa de difuzare pentru o retea. In IPv6 se
foloseste trimiterea multipla la grupul all-hosts.
2015
Comunicatie de grup - deziderate
• Toleranta la defecte prin replicarea serviciilor.
– Un serviciu replicat se realizeaza printr-un grup de servere.
– Mesajele clientilor trebuie trimise la toti membrii grupului de servere replicate.
Clientii vor fi deserviti chiar si la caderea unora dintre aceste servere.
• Localizarea serverelor de descoperire in interconectarea spontana.
– Mesajele multiplu-trimise se pot utiliza de servere si/sau clienti pentru localizarea
serviciilor de descoperire in vederea inregistrarii si/sau regasirii altor servicii ale SD
impreuna cu interfetele acestora..
• Imbunatatirea performantelor prin replicarea datelor.
– Datele replicate conduc la cresterea performantelor serviciilor.
– In anumite cazuri replicarea poate avea loc pe calculatoarele clientilor. Ori de cate
ori datele sunt actualizate, schimbarile sunt trimise la toate procesele replicilor.
• Propagarea instiintarilor in SD bazate pe evenimente.
– Aparitia unui eveniment determina instiintarea corespunzatoare a tutoror membrilor
unui grup de procese ce si-au manifestat interesul in evenimentul respectiv.
– Ex. intr-o retea sociala sau intr-un sistem de chat (IM – instant messaging) daca o
persoana si-a schimbat starea sau profilul, fiecare prieten primeste o instiintare.
2015

Adresarea in Internet
• Principala functie a Internet-ului este schimbul de date intre calculatoare.
Pentru aceasta fiecare calculator din Internet are asignata o adresa IP
• Versiunea cea mai raspinadita la ora actuala a protocolului IP este IPv4.
In IPv4 adresa unui calculator este un sir de 32 de biti. Acest sir se
reprezinta sub forma unui 4-uplu format din 4 octeti, separati prin cate un
punct. Exemplu: 151.23.40.3.
• Exista si versiunea IPv6 care foloseste 128 de biti
• Multimea de adrese IP este impartita in 4 clase
– Clasa A, 0 adresa retea (7) adresa calculator (24)
– Clasa B, 10 adresa retea (14) adresa calculator (16)
– Clasa C, 110 adresa retea (21) adresa calculator (8): 192. …
– Clasa D, 1110 adresa multicast (28): 224. …
• 127.0.0.1 = adresa de loopback. Datele trimise aici se intorc inapoi la
sursa. Este utila pentru testarea aplicatiilor de retea folosind un singur
calculator
2015
Clase de adrese in Internet

7 24
Class A: 0 Network ID Host ID

14 16
Class B: 1 0 Network ID Host ID

21 8
Class C: 1 1 0 Network ID Host ID

28
Class D (multicast): 1 1 1 0 Multicast address

27
Class E (reserved): 1 1 1 1 0 unused

2015

Trimiterea multipla IP – I
• Trimiterea multipla IP (engl.IP multicast) functioneaza peste
protocolul IP. Un pachet IP este adresat unui calculator.
Porturile apar in TCP si UDP, la nivelul transport.
• Trimiterea multipla permite expeditorului sa trimita un singur
pachet IP unei multimi de calculatoare care formeaza un grup
de trimitere multipla (engl.multicast group). Identitatea
destinatarilor individuali este transparenta expeditorului. Un
grup de trimitere multipla se identifica printr-o adresa IP de
clasa D – adica o adresa cu primii 4 biti egali cu 1110 in IPv4:
224.0.0.0 – 239.255.255.255.
• Apartenenta la un grup permite unui calculator sa receptioneze
toate pachetele IP adresate grupului. Apartenenta este
dinamica, ea permite intrarea si parasirea dinamica a grupului,
cat si inscrierea simultana la mai multe grupuri. Trimiterea de
pachete catre grup nu necesita apartenenta la grup. 2015
Trimiterea multipla IP – II
• Trimiterea multipla IP este disponibila programelor de aplicatie numai la
nivelul UDP. Un proces poate transmite pachete UDP la o adresa de
trimitere multipla si un numar de port. El poate intra intr-un grup prin
adaugarea soclului sau la grup.
• La nivel IP, un calculator apartine unui grup cand unul sau mai multe
dintre procesele sale are soclul apartinand grupului. Cand un mesaj de
trimitere multipla ajunge la un calculator, el este inaintat tuturor soclurilor
locale care sunt atasate adresei respective si au portul specificat in pachet.
• Pentru implementarea trimiterii multiple in retele IP se folosesc rutere
speciale pentru trimitere multipla (engl. multicast routers).
• Adresele de trimitere multipla pot fi permanente sau temporare.
• Grupurile permanente exista chiar si daca nu au membrii. Ele au destinatie
speciala, adresele lor fiind alocate de IANA – Internet Assigned Numbers
Authority: http://www.iana.org/
• Ex. adresa 224.0.0.1 e folosita de NTP – Network Time Protocol.
• Un grup temporar are nevoie de o adresa libera. Pentru a evita participarea
accidentala la un grup deja existent, se seteaza TTL la o valoare mica.
2015

Java API pentru trimitere multipla IP


• Clasa MulticastSocket.
– Este o subclasa a clasei DatagramSocket si ofera in plus capabilitatea de
intrare intr-un grup.
– Aceasta clasa are doi constructori: i) un constructor ce primeste ca
parametru numarul portului; ii) constructor fara parametrii care foloseste un
port local liber.
– Metoda joinGroup se foloseste pentru intrarea intr-un grup. Ea primeste
ca parametru adresa de IP a grupului, sub forma de obiect InetAddress.
– Metoda leaveGroup se foloseste pentru parasirea grupului.
– Metoda setTimeToLive seteaza valoarea timpului de viata. Implicit
aceasta valoare este 1, permitand doar difuzarea in reteaua locala.
• Exemplu:
– Se prezinta un program care preia de la linia de comanda un mesaj si o
adresa de grup.
– Programul (procesul) se inscrie la grup, trimite mesajul grupului, realizeaza
trei receptionari de mesaje de la membrii grupului si apoi se termina.
2015
Program Java pentru trimitere multipla IP – I
import java.net.*;
args[0] este mesajul
import java.io.*; args[1] este adresa de trimitere multipla
public class MulticastPeer {
public static void main(String args[]) {
MulticastSocket s = null;
try {
InetAddress group =
InetAddress.getByName(args[1]);
s = new MulticastSocket(6789); Crearea soclului legat la portul 6789
s.joinGroup(group); Inscriere in grup
byte [] m = args[0].getBytes();
DatagramPacket messageOut =
new DatagramPacket(m, m.length, group, 6789);
s.send(messageOut); Expediere mesaj la grup
System.out.println("sent");

2015

Program Java pentru trimitere multipla IP - II


byte[] buffer = new byte[1000];
for (int i=0; i< 3;i++) {
DatagramPacket messageIn = new DatagramPacket(buffer,
buffer.length);
System.out.println("prepare to receive");
s.receive(messageIn); Receptionarea a 3 mesaje
System.out.println("Received:" + trimise grupului
new String(messageIn.getData(), 0,
messageIn.getLength()));
}
s.leaveGroup(group);
System.out.println("left");
} catch (SocketException e) {
System.out.println("Socket: " + e.getMessage());
} catch (IOException e){System.out.println("IO: " +
e.getMessage());
} finally { if (s != null) s.close();}
}
}
2015
Sisteme distribuite obiectuale si
invocare la distanta

Capitolul 6

2015

Invocare la distanta
• Protocoale cerere – raspuns (engl. request – reply protocols)
– Ofera suport de nivel coborat pentru emiterea unor cereri de executie a
operatiilor la distanta
– Ofera suport direct metodelor RPC si RMI
– Se bazeaza pe serializarea datelor (engl. marshalling) si referinte la
distanta (engl. remote references)
• Apel de procedura la distanta (engl. remote procedure call –
RPC), aparut in 1984
– Permite unui program client sa apeleze in mod transparent o procedura
ce ruleaza intr-un proces server, aflat posibil pe un calculator diferit de
calculatorul clientului.
• Invocarea metodelor la distanta (engl. remote method
invocation – RMI)
– Permite unor obiecte aflate in procese diferite, posibil pe calculatoare
diferite sa comunice prin invocari de metode.
2015
Impachetarea si despachetarea datelor
• Structurile de date din programele in executie trebuie serializate sub forma
de mesaje ce constau din secvente de octeti. Structurile de date compuse
trebuie liniarizate, iar datele primitive trebuie convertite in format binar.
• Reprezentarile binare ale datelor primitive specifice diverselor platforme
pot sa difere. De ex., caracterele se pot codifica Unicode sau ASCII,
intregii pot avea lungimi si orientari diferite (big endian si little endian),
iar numerele reale pot folosi diverse reprezentari in virgula mobila.
• Exista doua metode de a realiza interschimbul de date:
– Valorile sunt convertite din formatul expeditorului in format extern inaintea
transmisiei si reconvertite din formatul extern in formatul destinatarului dupa receptie.
– Valorile sunt transmise direct in formatul expeditorului impreuna cu indicarea
explicita a formatului folosit.
• Un format extern comun de reprezentare a datelor primitive si a
structurilor de date compuse se numeste reprezentare externa a datelor.
• Procesul de conversie a unei structuri de date intr-o forma convenabila
pentru transmisie = impachetare (engl. marshalling). Procesul de
reconstruire a unei structuri de date dintr-un format folosit pentru
transmisie = despachetare (engl. unmarshalling).
2015

Reprezentari externe
• Formatul de serializare al obiectelor Java.
– Specific limbajului Java
– Fiecare obiect este serializat astfel incat sa poata fi refacut la
destinatie
– Serializarea contine si informatie despre clasa obiectului
• CDR – Common Data Representation) folosit de CORBA.
– Este un format intermediar in care se traduc structurile de date din
diverse limbaje de programare
• XML (eXtensible Markup Language) / JSON (JavaScript
Object Notation)
– Continut
– Schema: defineste tipul de continut
• Ontologii pentru interoperabilitate in Semantic Web
– OWL
2015
Referinte la distanta I
• Cand un client invoca o metoda a unui obiect aflat la distanta –
OD (engl. remote object) se va trimite un mesaj de invocare
catre procesul server care gazduieste obiectul. Acest mesaj
trebuie sa specifice obiectul referit.
• Referinta unui obiect la distanta (engl. remote object reference)
– ROD = identificator al unui obiect care este valid intr-un SD.
• In cadrul oricarui mesaj de invocare a unui OD se transmite un
ROD.
• ROD trebuie generate astfel incat sa se asigure unicitatea lor in
timp si spatiu. Deoarece pot exista mai multe procese ce
gazduiesc OD, trebuie ca ROD sa fie unice pe multimea tuturor
acestor procese. Chiar si dupa ce un OD a fost sters, ROD
corespunzatoare nu se va refolosi pentru a se evita referirea
unor obiecte eronate.
2015

Referinte la distanta II
• O reprezentare a unui ROD poate contine: adresa de IP a
calculatorului, numarul portului, data crearii OD, un numar
local al obiectului ce este incrementat automat de procesul
care a creat OD. La aceasta se poate adauga o descriere a
interfetei OD.
• In cazul in care un OD exista numai in cadrul procesului care
l-a creat si va dispare odata cu distrugerea acestuia, o ROD va
putea fi folosita pe post de adresa a obiectului.
• In cazul in care obiectele pot fi relocate intr-un alt proces pe
un calculator diferit, o ROD nu se va putea utiliza pe post de
adresa a obiectului, pentru aceasta existand tehnici speciale.
32 bits 32 bits 32 bits 32 bits

IP address interface of
port number time object number
remote object

2015
Protocol cerere-raspuns
Client Server

Request
doOperation
message getRequest
select object
(wait) execute
Reply method
message sendReply
(continuation)

• Este de obicei o operatie sincrona, clientul blocandu-se pana la


primirea raspunsului serverului.
• Este fiabila – raspunsul serverului este in acelasi timp si o
confirmare de primire a cererii de catre client.
• Pentru mesaje scurte este convenabil de implementat in UDP.
2015

Implementarea unui protocol cerere-raspuns


• Protocolul se bazeaza pe trei primitive de comunicare:
doOperation, getRequest si sendReply.
• Sistemele RMI si RPC se bazeaza pe un astfel de protocol.
public byte[] doOperation(RemoteRef o, int operationId,
byte[] args)
– se utilizeaza de clienti pentru a invoca o operatie la distanta.
– argumentele sale specifica un OD si metoda care se va invoca,
impreuna cu eventualele argumente. Rezultatul executiei acestei
metode este primirea unui raspuns. Clientul va impacheta datele
inainte de transmisie si le va despacheta dupa receptie.
public byte[] getRequest()
– se utilizeaza de procesul server pentru a prelua o cerere.
public void sendReply(byte reply[],InetAddress
clientHost,int clientPort)
– se utilizeaza de procesul server pentru a trimite un raspuns clientului.
2015
Structura mesajelor de cerere-raspuns
• messageType – indica tipul mesajului, 0 ⇒ cerere si 1 ⇒ raspuns.
• requestId – identificator al mesajului. O operatie doOperation a
clientului va genera acest identificator, iar serverul il va copia in mesajul
de raspuns.
• remoteReference – este o RD impachetata.
• operationId – este un identificator al operatiei invocate. In cazul in care
atat clientul cat si serverul folosesc un limbaj comun ce suporta tehnica
de reflectie (de exemplu Java), se va putea folosi o reprezentare a unei
metode in acel limbaj (de exemplu Method in Java).
• arguments – reprezentarea impachetata a argumentelor metodei.
messageType int (0=Request, 1= Reply)
requestId int
remoteReference RemoteRef
operationId int or Operation
arguments array of bytes
2015

Identificatori de mesaje
• Orice schema de gestiune a mesajelor intr-un SD ce presupune
asigurarea fiabilitatii si/sau implementarea unui protocol
cerere-raspuns cere ca fiecarui mesaj sa i se aloce un
identificator unic.
• Un identificator de mesaj are doua parti:
– requestId ce se genereaza prin incrementare de catre expeditor. Se
impune ca ciclul de viata al mesajului sa fie mai mic decat timpul in
care generatorul revine la 0.
– Identificatorul procesului expeditor: adresa de IP si numar port. Se
poate determina dintr-un pachet UDP
• Daca requestId se reprezinta pe n biti atunci valoarea sa
maxima este 2n-1. Dupa depasirea valorii maxime, valorile se
reiau prin incrementare de la 0. Se impune ca timpul in care se
epuizeaza toate valorile posibile sa fie mult mai mare decat
durata medie de viata a mesajului in sistem. 2015
Modelul de eroare al protocolului cerere-raspuns

• Daca cele 3 primitive doOperation, getRequest si


sendReply sunt implementate peste datagrame UDP
atunci ele vor suferi problemele UDP:
– i) erori de omisiune;
– ii) nu se garanteaza livrarea mesajelor in ordinea expedierii.

• In plus protocolul poate suferi de erori ale proceselor.


Sa presupunem ca acestea sunt erori de oprire
(engl.crash).

2015

Timeout
• Metoda doOperation trebuie sa foloseasca tehnica
timeout pentru a trata cazurile de oprire neasteptata a
serverului sau de pierdere a mesajelor. In acest caz
exista diverse optiuni:
– Retur imediat cu indicarea catre client ca operatia a esuat.
– Eroarea de timeout poate fi cauzata de pierderea mesajelor
de cerere sau de raspuns. In acest caz doOperation poate
emite cererea in mod repetat pana cand fie primeste un
raspuns, fie intarzierea de primire a raspunsului este
suficient de mare ca sa existe certitudine ca problema este de
la server, nu de la pierderea mesajelor.

2015
Inlaturarea mesajelor de cerere duplicate
• In cazurile in care cererea este retransmisa, serverul o
poate receptiona de mai multe ori. De exemplu, serverul
poate primi cererea, insa executarea cererii si emiterea
raspunsului de catre server poate dura mai mult decat
cuanta de timeout.
• Astfel ca exista posibilitatea ca serverul sa execute
cererea de mai multe ori.
• Din acest motiv, mesajele cu acelasi requestId trebuie
recunoscute si filtrate.
• Daca insa raspunsul nu a fost inca transmis, nu trebuie sa
se execute nici o actiune speciala.

2015

Pierderea mesajelor de raspuns


• Daca un server a trimis deja raspunsul la o cerere pe
care o primeste in duplicat, el va trebui sa o reexecute
daca nu a stocat rezultatul prelucrarii initiale.
• O operatie se numeste idempotenta daca executia sa
repetata va produce un acelasi rezultat. De exemplu,
adaugarea unui element la o multime este o operatie
idempotenta, insa adaugarea unui element la o
secventa nu este o operatie idempotenta.
• Un server ale carui operatii sunt toate idempotente nu
trebuie sa aiba in vedere masuri speciale pentru
evitarea executiei repetate ale aceleiasi operatii.

2015
Istoricul interactiunii
• Pentru serverele care necesita retransmisia raspunsului fara a reexecuta
operatia trebuie gestionata istoria interactiunii.
• Se numeste istorie o structura care contine mesajele de raspuns care au
fost transmise. O intrare in aceasta structura contine un identificator al
cererii, un mesaj de raspuns si identificatorul clientului catre care a fost
transmis. Aceasta structura se foloseste pentru a permite serverului sa
retransmita mesajele de raspuns la cererile clientilor.
• Pentru ca structura sa nu devina prea mare serverul trebuie sa poata decide
cand anumite raspunsuri nu mai trebuie pastrate in istorie. Deoarece un
client face o singura cerere la un moment dat, serverul poate interpreta
fiecare noua cerere drept o confirmare a raspunsului anterior. De aceea
istoria poate pastra doar ultimul mesaj de raspuns trimis fiecarui client.
• Tot sunt insa probleme daca numarul clientilor este mare.
• Deoarece cand un client se termina el nu va confirma ultimul raspuns
primit, acesta va trebui sa fie inlaturat automat din istorie dupa un anumit
timp.
2015

Variante de protocoale pentru cereri (I)


• Pentru implementarea apelului de proceduri la distanta
(engl.remote procedure call – RPC) s-au folosit trei protocoale,
cu semantici diferite in prezenta erorilor de comunicatie: i)
protocolul cerere (engl.request – R); ii) protocolul cerere-
raspuns – RR; iii) protocolul cerere-raspuns-confirmare
raspuns (engl.request-reply-acknowledgement – RRA.
Nume Mesaj trimis de

Client Server Client


R Cerere
RR Cerere Raspuns

RRA Cerere Raspuns Confirmare raspuns


2015
Variante de protocoale pentru cereri (II)
• Protocolul R poate folosit cand nu exista valori returnate catre client in
urma apelului si clientul nu are nevoie de confirmare ca procedura a fost
executata. Clientul isi poate continua executia imediat dupa transmiterea
apelului, nefiind nevoie sa astepte un rezultat sau confirmare
• Protocolul RR este folosit in majoritatea interactiunilor client-server. Nu
este necesara confirmarea deoarece raspunsul serverului este interpretat
drept confirmare a cererii clientului, iar o cerere ulterioara a clientului este
interpretata drept confirmare de primire a raspunsului serverului la cererea
precedenta.
• Protocolul RRA foloseste un mesaj de confirmare de la client ca a primit
raspunsul serverului. Aceasta confirmare este folosita de server pentru a
inlatura intrari de istorie. Primirea unei confirmari cu requestId se
interpreteaza drept confirmare a primirii raspunsurilor cu un identificator
mai mic decat requestId. Astfel, pierderea mesajelor de confirmare a
raspunsului nu creaza probleme. In plus confirmarea nu blocheaza
clientul.
2015

Interfete (I)
• Limbajele moderne de programare permit organizarea
programelor ca multimi de module ce comunica intre ele.
Comunicarea se face printr-o interfata pentru fiecare modul in
parte.
• Interfata unui modul specifica metodele si variabilele ce pot fi
accesate din alte module.
• Modulele unui SD pot rula in procese separate. Astfel ca un
modul nu va putea accesa variabilele din alt modul. Chiar daca
de exemplu se poate specifica accesul la anumite atribute,
accesul propriuzis se va face prin medode getter si setter.
• Tehnicile clasice de transfer a parametrilor (apel prin valoare si
apel prin referinta) nu sunt potrivite cand apelantul si apelatul
sunt in procese diferite.
2015
Interfete (II)
• Specificarea unei proceduri sau metode intr-o interfata a unui modul intr-
un SD se face prin parametrii de intrare/iesire.
– Parametrii de intrare sunt transmisi modulului la distanta prin trimiterea valorilor lor
intr-un mesaj de cerere si apoi folosirea lor drept argumente pentru executarea
operatiei la server.
– Parametrii de iesire sunt returnati in mesajul de raspuns si sunt utilizati drept rezultat
al apelului sau vor inlocui valorile variabilelor corespunzatoare din mediul apelului.
– Cand un parametru este atat de intrare cat si de iesire, valoarea corespunzatoare va fi
transmisa atat in mesajul de cerere cat si in cel de raspuns.
• Deoarece pointerii dintr-un proces nu sunt valizi intr-un alt proces, ei nu
se transmit ca argumente si nu se returneaza ca rezultate in apeluri la
distanta.
• In modelul client-server, serverul furnizeaza o interfata pentru servicii –
IS (engl.service interface). In SD obiectuale, un OD furnizeaza o interfata
la distanta – ID (engl.remote interface). Intre ele exista diferenta ca
metodele dintr-o ID pot transmite obiecte si/sau ROD ca argumente si pot
returna obiecte si/sau ROD ca rezultate.
2015

Limbaje de definire a interfetelor


• RMI poate fi integrata intr-un limbaj de programare care permite definirea
interfetelor. Astfel parametrii de intrare si iesire pot fi mapati pe utilizarea
normala a parametrilor din acel limbaj (de ex.Java RMI). Este utila cand
aplicatia distribuita este scrisa intr-un singur limbaj.
• Pot exista diverse servicii deja scrise in C++ sau in alte limbaje de
programare. Este benefic sa se asigure accesul la distanta la acestea din
programe scrise in limbaje de programare diferite. Astfel s-au proiectat
limbaje de definire a interfetelor (engl.Interface Definition Language –
IDL) care permit OD scrise in limbaje diferite sa se invoce unele pe altele.
• Un IDL este o notatie pentru interfete. Pentru fiecare parametru al unei
interfete se specifica: i) daca este de intrare si/sau de iesire; ii) tipul sau.
• Exemple de IDL:
– CORBA IDL
– IDL pentru RPC in DCE (Distributed Computing Environment, al OSF) – DCE IDL,
foloseste sintaxa C.
– DCOM IDL (bazat pe DCE IDL), folosit de DCOM (Distributed Common Object
Model, al firmei Microsoft).
– WSDL pentru servicii web. 2015
Comunicatia intre obiecte in SD obiectuale
• Modelul obiectual al unui SD extinde modelul obiectual clasic prin OD.
• Trebuie tratate urmatoarele probleme:
– Elementele modelul obiectual: pornind de la modelul obiectual clasic, relevante
pentru discutia referitoare la SD obiectuale.
– SD obiectuale: SD ce folosesc modelul obiectual
– Modelul obiectual distribuit: o extensie a modelului obiectual in vederea aplicarii sale
SD
– Consideratii de proiectare: i) in timp ce invocarile locale se executa o singura data, ce
semantica trebuie adoptata pentru invocarile la distanta ? ii) cum se poate realiza o
semantica a RMI cat mai apropiata de cea a invocarilor locale si ce diferente nu pot fi
eliminate ?
– Implementare: se arata cum se poate proiecta un nivel middleware aflat deasupra
protocolului cerere-raspuns pentru a asigura suportul necesar RMI intre OD ale unei
aplicatii distribuite
– Colectarea distribuita a gunoaielor (engl.distributed garbage collection): o prezentare
a unui algoritm de colectare distribuita a gunoaielor ce poate fi folosit intr-o
implementare a RMI

2015

Modelul obiectual I
• O aplicatie obiectuala consta dintr-o multime de obiecte ce
interactioneaza. Un obiect incapsuleaza date si cod. Vom presupune ca
accesul la datele private ale unui obiect se poate face numai prin
intermediul metodelor sale.
• Referinte la obiecte. Obiectele sunt accesate prin referinte. Invocarea
metodelor unui obiect se face prin intermediul referintei la obiect.
Obiectul a carui metoda a fost invocata se numeste obiect tinta
(engl.target) sau receptor (engl.receiver). Referintele pot fi atribuite
variabilelor, transmise ca argumente metodelor sau returnate ca rezultate
ale metodelor.
• Interfete. O interfata defineste semnaturile unei multimi de metode. Un
obiect furnizeaza o anumita interfata daca clasa sa contine cod ce
implementeaza metodele interfetei respective. O clasa poate implementa
mai multe interfete. O interfata defineste un tip ce se poate folosi in
declaratii de variabile sau parametrii.

2015
Modelul obiectual II
• Actiuni. O actiune se initiaza cand un obiect invoca o metoda a
altui obiect. Obiectul receptor executa metoda corespunzatoare
si eventual intoarce controlul obiectului apelant. O invocare
poate avea doua efecte:
– schimbarea starii obiectului receptor;
– crearea de noi obiecte;
– invocari ulterioare de metode ale altor obiecte.
• Exceptii. Exceptiile sunt metode elegante de a trata erorile, fara
complicarea codului. Ele separa clar codul de tratare a erorilor
de codul pentru o executie normala.
• Colectarea gunoaielor. Este mecanismul prin care se asigura
eliberarea automata a spatiului de memorie ocupat de obiectele
care nu mai sunt necesare.
2015

SD obiectuale
• Starea unui obiect este multimea valorilor variabilelor membre. In acest
fel starea unui program obiectual este partitionata logic intr-o multime de
obiecte. Distribuirea fizica a acestor obiecte in procese si/sau calculatoare
diferite este o extensie naturala a modelului obiectual.
• SD obiectuale pot adera la o arhitectura client-server. Obiectele sunt
gestionate de servere iar clientii pot invoca metodele acestora folosind
RMI. Obiectele din servere pot fi la randul lor clienti ale unor obiecte din
alte servere.
• Obiectele dintr-un SD pot fi replicate pentru cresterea tolerantei la defecte
si imbunatatirea performantelor sau pot migra pentru cresterea
performantei si a disponibilitatii.
• Obiectele pot folosi primitive de sincronizare pentru a-si asigura accesul
concurent corect la propriile variabile membre.
• Accesul la obiecte doar prin metode este un prim pas spre independenta de
formatul de reprezentare si de caracteristicile fizice ale platformei gazda.

2015
Modelul obiectual distribuit (I)
• Are la baza doua concepte fundamentale: i) referinta unui obiect la
distanta (engl.remote object reference) – ROD; ii) interfata la distanta
(engl.remote interface) – ID.
• ROD este o extensie a conceptului de referinta a unui obiect la SD. O
ROD este un identificator care se poate folosi intr-un SD pentru referirea
la un obiect unic. ROD se folosesc pentru invocarea unei metode a unui
OD si pot fi transmise ca argumente si intoarse ca rezultate in RMI.
• O ID specifica metodele unui OD care pot fi invocate prin RMI de catre
alte obiecte. In CORBA, definirea ID se face folosind limbajul CORBA
IDL. In Java RMI, o ID se defineste prin extinderea interfetei Remote.
• Actiunile intr-un SD obiectual pot genera lanturi de RMI.

remote local C
invocation invocation local E
invocation remote
invocation F
B local
A
invocation D
2015

Modelul obiectual distribuit (II)


• Daca un limbaj suporta colectarea gunoaielor, sistemul RMI asociat va
trebui sa asigure colectarea gunoaielor corespunzatoare OD. Acest lucru
se realizeaza de obicei printr-o cooperare intre colectorul local de gunoaie
si un modul care realizeaza colectarea distribuita a gunoaielor.
• Orice invocare la distanta poate esua: i) datorita faptului ca procesul ce
contine OD fie s-a oprit, fie este prea solicitat si nu poate raspunde la
timp; ii) deoarece mesajul de cerere sau de raspuns s-a pierdut. Din acest
motiv o invocare la distanta trebuie sa poata genera o exceptie ce sa
indice fie depasirea unui timeout, fie o eroare in executia metodei.

remoteobject

Data
remote
interface
m1 implementation m4

{ m2
m3 of methods
m5
m6

2015
Instantierea OD
• AD pot contine OD ce dispun de metode speciale – gen
constructor, pentru instantierea altor OD ce pot fi ulterior
invocate prin RMI.
• Spre exemplu, obiectul L din figura de mai jos contine o
metoda pentru crearea de OD. Astfel ca in urma invocarii la
distanta de catre obiectele C si K ale metodei constructor din
obiectul L vor fi create 2 OD si anume M si N.

2015

Semantica RMI
• Am aratat ca implementarea functiei doOperation in protocolul RR se poate face in
diverse moduri, asigurandu-se diverse nivele ale garantarii livrarii parametrilor:
– Reincercarea de a transmite mesajul de cerere: mesajul de cerere este retransmis pana cand se
receptioneaza un raspuns sau se presupune ca serverul s-a oprit.
– Filtrarea duplicatelor: cand se utilizeaza retransmiterea, cererile duplicate sunt filtrate si
eliminate de catre server.
– Retransmisia rezultatelor: se pastreaza o istorie a mesajelor cu rezultatele, pentru a permite
retransmiterea fara reexecutarea operatiilor la server.
• Diverse combinatii ale acestor variante conduc la o varietate de semantici posbile pentru
fiabilitatea RMI din punctul de vedere al apelantului.

Fault tolerance measures Invocation


semantics

Retransmit request Duplicate Re-execute procedure


message filtering or retransmit reply
No Not applicable Not applicable Maybe
Yes No Re-execute procedure At-least-once
Yes Yes Retransmit reply At-most-once 2015
Semantica invocarii maybe
• In acest caz apelantul nu va putea sti cu siguranta daca invocarea s-a
executat sau nu.
• Aceasta situatie apare cand nu s-a luat nici una dintre masurile de
toleranta la defecte. Putem avea urmatoarele tipuri de erori:
– i) erori de omisiune in cazul in care mesajul de invocare sau de rezultat s-a pierdut;
ii) erori de oprire in cazul in care serverul ce contine OD se defecteaza.
• Daca mesajul de rezultat nu a fost receptionat dupa scurgerea cuantei de
timeout si nu exista reincercari, nu exista certitudinea ca metoda s-a
executat sau nu. Se poate insa ca metoda sa se fi executat, dar mesajul cu
rezultatul sa se fi pierdut. Mai mult, in cazul unui sistem asincron este
posibil ca mesajul de raspuns sa soseasca dupa timeout.
• Aceasta semantica este utila in aplicatiile in care eventualele invocari
esuate sunt acceptabile.

2015

Semantica invocarii at-least-once


• In acest caz apelantul fie primeste un rezultat, in cazul in care
apelul s-a executat cel putin o data, fie o exceptie ce il
informeaza ca nu s-a receptionat nici un rezultat.
• Aceasta semantica se poate realiza prin retransmisia mesajelor
de cerere, fapt ce mascheaza eventualele erori de omisiune in
mesajele de cerere sau raspuns.
• Sufera de urmatoarele tipuri de erori: i) erori de oprire ale
serverului ce contine OD; ii) erori arbitrare, in cazul in care
retransmiterea mesajului de invocare poate conduce la
receptionarea multipla si executia multipla a metodei invocate,
fapt ce poate determina stocarea si returnarea unor valori
eronate (se intampla in cazul operatiile neidempotente).
• Aceasta semantica este acceptabila atunci cand metodele ID
sunt toate idempotente.
2015
Semantica invocarii at-most-once
• In acest caz apelantul fie primeste un raspuns, in cazul
in care apelul s-a executat exact o data, fie o exceptie
ce il informeaza ca nu s-a receptionat nici un rezultat.
• Aceasta semantica se poate realiza prin utilizarea
tuturor masurilor de toleranta la defecte. Utilizarea
reincercarilor va duce la mascarea erorilor de omisiune
a mesajelor de invocare sau de rezultat. Masurile
aditionale previn erorile arbitrare asigurandu-se ca
pentru fiecare invocare o metoda se va executa cel mult
o singura data.

2015

Transparenta RMI
• In general, invocarile la distanta sunt similare cu invocarile locale din
punct de vedere sintactic.
• Cu toate acestea, invocarile la distanta sunt mai vulnerabile la erori decat
invocarile locale. Indiferent de semantica adoptata, exista intotdeauna
posibilitatea sa nu se obtina nici un rezultat si in cazul unei erori sa nu se
distinga intre o eroare de retea si o eroare in procesul server. Din acest
motiv trebuie ca obiectele care efectueaza invocari la distanta sa poata
recupera din eventualele erori.
• Astfel se apreciaza ca diferentele dintre invocarile locale si invocarile la
distanta trebuie sa existe la nivelul interfetelor. Spre exemplu, in Java
RMI, OD se disting prin faptul ca implementeaza interfata Remote. Ele
pot genera exceptii RemoteException.
• Implementatorii OD cu interfetele specificate printr-un IDL vor avea in
vedere faptul ca aceste obiecte pot fi accesate concurent de clienti
multiplii, trebuind sa ia masurile de proiectare corespunzatoare.
• O alta varianta o reprezinta RMI tranzactional – unui apel la distanta i se
ataseaza proprietati de tranzactie – ACID.
2015
Implementarea RMI
• Consta dintr-o multime de obiecte si module ce includ:
– Modulul de comunicatie
– Modulul de gestiune a ROD
– Software-ul de RMI, ce contine obiectele proxy, skeleton si dispatcher.

2015

Modulul de comunicatie
• Exista doua module de comunicatie care interactioneaza cu un
protocol RR. Aceste module vor folosi doar primele trei
campuri din cadrul mesajelor de cerere-raspuns: messageType,
requestId si remoteReference (pe post de ROD). Campurile
operationId si arguments sunt tratate separat de software-ul de
RMI.
• Modulele de comunicatie sunt responsabile sa asigura o
anumita semantica, de exemplu at-most-once.
• Modulul de comunicatie din server selecteaza obiectul
dispatcher corespunzator clasei obiectului invocat. Pentru
aceasta el obtine referinta locala a obiectului de la modulul
pentru referinte la distanta, dupa ce i-a transmis ROD din
cadrul mesajului de cerere.

2015
Modulul de gestiune a ROD
• Este responsabil cu traducerea intre referintele locale si ROD si pentru
crearea ROD. Pentru aceasta el gestioneaza o tabela de obiecte la distanta
(engl.remote object table) – TOD.
• TOD memoreaza corespondenta intre referintele locale in cadrul
procesului si ROD. Tabela include:
– cate o intrare pentru fiecare OD continut de procesul server;
– cate o intrare pentru fiecare obiect proxy local.
• Modulul este apelat de software-ul de RMI, cand se impacheteaza sau
despacheteaza ROD.
• Actiunile acestui modul sunt:
– cand un OD este transmis ca argument sau intors ca rezultat pentru prima oara, acest
modul este interogat pentru a crea o ROD pentru acest obiect, acest ROD fiind
adaugat la tabela;
– cand se primeste un mesaj de cerere sau raspuns cu un ROD, modulul este interogat
pentru a determina referinta locala corespunzatoare. Ea poate fi un obiect proxy sau o
referinta la OD propriuzis. Daca ROD nu este in taabela, atunci se creaza un nou
obiect proxy si se adauga la tabela.
2015

Software-ul de RMI

• Este un nivel intermediar intre obiectele aplicatiei si


modulele de comunicatie si gestiune a ROD.

• Are componentele:
– Obiectul proxy sau stub.
– Obiectul dispatcher.
– Obiectul skeleton.

2015
Obiectul proxy sau stub
• Rolul unui obiect proxy este de a face invocarea metodelor la
distanta transparenta pentru client; ele vor delega invocarea
catre OD, ascunzand: referirea OD, impachetarea argumentelor,
despachetarea rezultatului si expedierea/receptia mesajelor.
• Exista cate un obiect proxy pentru fiecare OD referit dintr-un
proces client ce detine o ROD. Clasa obiectului proxy
implementeaza metodele ID ale OD pe care il reprezinta, dar
diferit de OD. Fiecare metoda a obiectului proxy impacheteaza
o ROD la obiectul tinta, propriul operationId si argumentele
sale intr-un mesaj de cerere trimis catre server. Apoi asteapta
un mesaj de raspuns, despacheteaza rezultatul si il intoarce
obiectului apelant.

2015

Obiectul dispatcher
• Un server are cate un obiect dispatcher (dispecer) si un
obiect skeleton (schelet) pentru fiecare clasa
reprezentand un OD. Obiectul dispecer primeste
mesajul de cerere de la modulul de comunicatie si
utilizeaza campul operationId pentru a selecta metoda
corespunzatoare din obiectul schelet. Obiectele
dispecer si schelet utilizeaza acelasi operationId pentru
metodele ID.

2015
Obiectul skeleton
• Acest obiect (schelet) implementeaza metodele din ID.
Implementarea este insa diferita fata de cea din OD,
continand un cod “liant” cu mesajele de cerere /
raspuns, pe langa invocarea metodelor OD.
• O metoda a scheletului:
– despacheteaza argumentele metodei din mesajul de cerere
– invoca metoda corespunzatoare din OD
– asteapta terminarea invocarii
– impacheteaza rezultatul, impreuna cu exceptiile, intr-un
mesaj de raspuns catre mesajul de cerere expediat de
obiectul proxy.

2015

Probleme la implementarea RMI (I)


• Generarea claselor pentru obiectele proxy, dispecer si schelet. Acest lucru
se realizeaza automat de catre un compilator de interfete. Spre exemplu:
– In CORBA interfetele sunt specificate in CORBA IDL si din ele se genereaza cod
C++ pentru clasele proxy, dispecer si schelet.
– In Java RMI, multimea metodelor unui OD se defineste intr-o interfata Java. Ea
trebuie apoi implementata in cadrul clasei OD. Compilatorul de Java RMI genereaza
clasele proxy, dispecer si schelet din clasa corespunzatoare OD.
• Programele client si server.
– Programul server contine clasele dispecer si schelet, impreuna cu clasele
corespunzatoare tuturor OD gazduite de server (numite si clase servant). In plus,
serverul contine si o sectiune de initializare, de exemplu intr-o metoda main in Java
sau C++. Ea este responsabila cu crearea si initializarea cel putin a unuia dintre OD
gazduite de server. OD aditionale pot fi create ca raspuns la cererile clientilor.
Sectionea de initializare poate de asemenea sa inregistreze unele OD cu servicu de
nume (engl.binder). In general se inregistreaza un singur obiect, care va fi folosit sa
le acceseze pe celelalte.
– Programul client contine clasele obiectelor proxy corespunzatoare OD. Poate folosi
servicul de nume pentru a regasi ROD.

2015
Probleme la implementarea RMI (II)
• Metode factory. Am aratat ca ID nu pot contine constructori. Acest lucru
inseamna ca OD nu pot fi create prin invocarea la distanta a constructorilor. OD
se creaza fie in sectiunea de initializare a serverului, fie printr-o ID proiectata
special pentru aceasta. Termenul de metoda factory este folosit pentru a indica o
metoda de creare a OD. Un obiect factory este un obiect creat cu o metoda
factory. Orice OD care trebuie sa poata crea noi OD la cerere trebuie sa
furnizeze metode in propria ID pentru acest scop.
• Serviciul de nume (engl.binder). In general, programele client necesita o
modalitate de a putea obtine o ROD pentru cel putin un OD gazduit de server.
Un serviciu de nume intr-un SD este un serviciu separat care gestioneaza o
tabela cu maparile numelor textuale ale OD la ROD. Acest serviciu este utilizat
de programele server pentru inregistrarea OD pe care le gazduiesc si de
programele client pentru regasirea lor. Serviciul de nume Java RMI este
RMIRegistry, iar servicul de nume CORBA este CORBA Naming Service.
• Fire pe server. Ori de cate ori un obiect executa o invocare la distanta, executia
poate conduce la alte invocari de metode, eventual la distanta, inainte de
intoarcerea unui rezultat. Pentru a se evita ca o invocare la distanta sa provoace
intarzieri ale unor invocari ulterioare din acelasi obiect, in general serverele
aloca cate un fir separat pentru executia fiecarei invocari la distanta. 2015

Activarea OD
• Unele aplicatii cer ca informatiile sa supravietuiaca perioade lungi de timp. Nu este insa
practic ca obiectele ce gestioneaza aceste informatii sa fie mentinute in cadrul proceselor
in executie pentru un timp nelimitat, deoarece ele nu sunt efectiv folosite in tot acest
timp. Pentru a se evita pierderea de resurse datorata executiei continue a serverelor ce
gazduiesc OD, se poate recurge la pornirea acestor servere ori de cate ori acest lucru este
cerut de catre clienti. Procesele care pornesc procese server se numes activatori
(engl.activator), de exemplu serviciul Inetd din Linux.
• Un OD este activ cand este disponibil pentru RMI intr-un proces in executie. Altfel el
este pasiv, dar poate fi activat. Un OD pasiv consta din 2 parti: i) implementarea
metodelor; ii) starea sa in forma impachetata.
• Activarea unui OD consta din crearea unui obiect activ din obiectul pasiv asociat prin
crearea unei noi instante a clasei si initializarea variabilelor membre din starea salvata.
Activarea poate avea loc la cerere, de exemplu cand obiectul este invocat de alt obiect.
• Un proces activator are urmatoarele responsabilitati: i) inregistrarea obiectelor pasive
care sunt disponibile pentru activare. Acest lucru presupune inregistrarea numelor
serverelor la URL-urile sau numele fisierelor corespunzatoare obiectelor pasive; ii)
pornirea proceselor server si activarea OD din cadrul lor; iii) Monitorizarea locatiilor
serverelor pentru OD ce au fost deja activate.
• In CORBA activatorul se cheama implementation repository. In Java RMI exista cate un
activator pentru fiecare calculator server.
2015
Persistenta obiectelor
• Un obiect care transcede peste activarile/dezactivarile proceselor server se numeste
obiect persistent – OP. Un astfel de obiect este in general gestionat de o memorie de OP
– MOP care stocheaza starea sa in forma impachetata pe disc.
• O MOP gestioneaza un numar mare de OP. Ele sunt activate in momentul invocarii lor de
catre alte obiecte. Activarea este transparenta din punctul de vedere al obiectului apelant.
Cand nu mai sunt necesare in memorie, OP sunt pasivizate si salvate in MOP. MOP are
nevoie de o strategie pentru pasivizarea OP (de exemplu la sfarsitul unei tranzactii, cand
OP au o stare consistenta, sau la terminarea programului). MOP realizeaza si o
optimizare, salvand doar acele obiecte care au fost modificate de la ultima salvare.
• MOP permit in general organizarea OP sub forma de colectii cu nume interpretabile de
un agent uman – URL sau cale in sistemul de fisiere.
• Exista doua abordari pentru a decide daca un obiect este OP sau nu: i) MOP gestioneaza
multimea radacinilor colectiilor de obiecte persistente si orice obiect care este accesibil
dintr-o astfel de radacina este OP. Aceasta abordare este folosita de Persistent Java.
MOP ce folosesc aceasta abordare se bazeaza pe un colector de gunoaie pentru a elimina
obiectele care nu mai sunt accesibile dintr-o radacina persistenta; ii) MOP utilizeaza
clase speciale pe care se bazeaza persistenta. Un OP apartine unei astfel de subclase.
Obiectele care nu mai sunt necesare trebuie sterse explicit (abordare specifica C++).

2015

Probleme la implementarea RMI – localizarea obiectelor (IV)

• In momentul in care un OD ramane in acelasi proces unde a fost creat, pe


durata intregului sau ciclu de viata, ROD bazate pe adresa de IP si
numarul portului pot fi folosite pe post de adresa a obiectului. Dar exista
posibilitatea ca un OD sa calatoreasca in diverse procese, posibil pe
calculatoare diferite, in ciclul sau de viata. In acest caz ROD nu mai
poate fi folosita pe post de adresa a obiectului. Clientii acestui OD vor
avea nevoie atat de ROD cat si de adresa OD.

• Se poate folosi un serviciu de localizare (engl.location service) pentru


localizarea unui obiect pe baza ROD. El foloseste o tabela care mapeaza
ROD intr-o locatie probabila a OD (probabila deoarece este posibil ca
OD poate sa fi migrat intre timp de acolo). Gasirea locatiei se poate baza
pe o schema care combina un mecanism de cache cu un mecanism de
difuzare (engl.broadcast) si poate fi imbunatatita prin folosirea unor
pointeri la locatiile urmatoare (engl.forward location pointer).
2015
Colectarea distribuita a gunoaielor (I)
• Scopul unui colector distribuit de gunoaie (engl.distributed garbage collector)
este sa se asigure ca daca o referinta locala la un obiect sau o ROD sunt pastrate
intr-o multime distribuita de obiecte, atunci obiectul respectiv va continua sa
existe, insa imediat ce nu mai exista obiecte care il refera, obiectul poate fi
eliminat si memoria ocupata poate fi eliberata.
• Java foloseste un algoritm de colectare distribuita a gunoaielor bazat pe
contorizarea referintelor. Fiecare OD de pe server va trebui informat ori de cate
ori o ROD apare, respectiv nu mai este folosita, intr-un proces client, prin
intermediul unui obiect proxy.
• Colectorul distribuit coopereaza cu colectorul local in maniera urmatoare:
– Fiecare proces server gestioneaza multimea proceselor client (masini virtuale in cazul
Java) care folosesc o ROD a unui OD al sau (multimea holders a acelui OD). Ea se
poate pastra ca o coloana suplimentara a tabelei de OD din cadrul sau.
– Cand un client C primeste pentru prima oara o ROD pentru un obiect particular B, va
face o invocare addRef(B) catre serverul ce contine B si apoi creaza obiectul proxy.
Serverul va adauga apoi pe C la multimea holders a lui B.
– Cand colectorul de gunoaie al clientului C observa ca obiectul proxy al lui B nu mai
este accesibil, va executa o invocare removeRef(B). Acest lucru va elimina pe C din
multimea holders a lui B.
– Cand multimea holders a lui B devine vida, colectorul local al serverului va elibera
spatiul ocupat de B daca nu exista nici o referinta locala la el.
2015

Colectarea distribuita a gunoaielor (II)


• Algoritmul prezentat foloseste o comunicatie cerere-raspuns cu o semantica at-
most-once intre invocarile modulelor de gestiune ROD ale celor doua procese.
Facem observatia ca apelurile suplimentare datorate algoritmului de colectare nu
afecteaza operarea normala a RMI; ele apr doar la crearea, respectiv eliminarea
obiectelor proxy.
• Colectorul distribuit Java tolereaza defectele de comunicatie in felul urmator.
Operatiile addRef si removeRef sunt idempotente. Daca addRef genereaza o
exceptie, fapt ce inseamna ca fie a fost exeutata o singura data, fie nu a fost
executata, atunci clientul nu va crea obiectul proxy, dar va executa removeRef.
Daca si removeRef esueaza problema se rezolva prin mecanismul de inchiriere.
• Colectorul distribuit Java tolereaza defectele la client prin mecanismul de
inchiriere (engl.lease). Serverele inchiriaza OD pe care le gazduiesc clientilor lor
pentru o perioada limitata de timp. Este responsabilitatea clientilor sa ceara
reinnoirea inchiriererii in mod explicit. Perioada de inchiriere incepe atunci cand
un client executa o invocare addRef catre server. Inchirierea se termina fie la o
invocare removeRef, fie la expirarea cuantei de timp. Pentru fiecare inchiriere
serverul pastreaza identificatorul masinii virtuale a clientului si perioada
inchirierii.
2015
Privire de ansamblu a Java RMI
• O aplicatie Java RMI contine doua tipuri de procese: server si client.
• Serverul creaza OD, face disponibile referintele la OD si asteapta clientii
sa invoce metode asupra acestor OD.
• Clientul obtine una sau mai multe referinte la OD si invoca metodele lor.
• RMI permite clientului si serverului sa schimbe informatie prin invocare
de metode: parametrii de la client la server, rezultate de la server la client.
• O aplicatie obiectuala distribuita – AOD realizeaza urmatoarele operatii :
– Localizarea OD prin diverse metode: i) procesele server inregistreaza OD in registrul
RMI – RMI registry folosind serviciul de nume al RMI; un client poate regasi un
ROD dupa numele OD prin acces la acest registru; ii) procesele pot transmite
parametrii OD si apelurile de metode RMI pot returna ROD;
– Comunicarea cu OD: detaliile acestei comunicari sunt rezolvate de software-ul de
RMI astfel incat pentru programatorul de aplicatie comunicarea cu un OD sa fie
similara invocarii locale a unei metode Java;
– Incarcarea definitiilor de clase pentru obiectele transmise intre procese: Deoarece
RMI permite transferul obiectelor intre procese, el asigura ca un proces sa obtina
definitia clasei obiectului, cat si datele corespunzatoare obiectului respectiv.
2015

Schema unei aplicatii Java RMI

• Serverul inscrie OD in registru si ii asigneaza/leaga (engl.bind) un nume


• Clientul regaseste un OD in registru dupa nume si determina o ROD
• Sistemul RMI acceseaza un server Web pentru a descarca definitii de
clase de la server la client sau invers, pentru diverse OD, atunci cand este
necesar.
2015
Descarcarea dinamica a codului

• Unul dintre avantajele centrale si unice ale RMI este


posibilitatea descarcarii dinamice a codului clasei unui obiect
atunci cand clasa obiectului nu este disponibila in masina
virtuala Java a receptorului obiectului respectiv.
• Clasa unui obiect (semnaturi si comportament) disponibila
initial in cadrul unei masini virtuale Java – JVM din sistem
poate fi transmisa altei JVM, posibil aflata la distanta.
• Prin transmiterea clasei impreuna cu obiectul, comportamentul
obiectului nu se modifica atunci cand obiectul este trimis pe o
alta JVM.
• Acest lucru permite posibilitatea extinderii dinamice a
comportamentului unei aplicatii.
2015

Interfete la distanta, obiecte, metode


• O AOD este construita din interfete si clase. Intefetele declara
metode si clasele definesc metodele declarate in interfete si
posibil alte metode aditionale.
• Un OD implementeaza o interfata la distanta – ID:
– O ID va extinde interfata java.rmi.Remote
– Fiecare metoda din ID declara o exceptie java.rmi.RemoteException,
pe langa alte eventuale exceptii specifice aplicatiei respective
• Accesul la un OD se face prin intermediul unui reprezentant
local al acestuia numit stub sau proxy. Astfel un client va
invoca o metoda asupra obiectului stub, acesta fiind
responsabil pentru comunicarea cu serverul si executia
metodei asupra OD corespunzator pe server.
• Un obiect stub corespunzator unui OD implementeaza acelasi
set de ID ca si OD.
2015
Crearea unei AOD folosind Java RMI
• Proiectarea si implementarea componentelor AOD: consta in
determinarea arhitecturii aplicatiei incluzand specificarea ce componente
sunt locale si ce componente sunt accesibile la distanta:
– Definirea ID. Proiectarea ID presupune determinarea metodelor ce vor fi disponibile
la distanta si a parametrilor si valorilor returnate.
– Implementarea OD. Un OD va implementa una sau mai multe ID. Un OD poate
implementa in plus si alte interfete si metode disponibile local. Daca implementarea
parametrilor si valorilor returnate de aceste metode necesita clase locale, acestea se
vor implementa.
– Implementarea clientilor. Se poate face oricand dupa implementarea OD. Un client
la distanta va avea acces doar la ID, nu si la modul de implementare al acestora.
• Compilarea surselor.
• Disponibilizarea claselor in retea. Se refera la disponibilizarea ID si a
claselor ce trebuie descarcate de clienti sau servere.
• Pornirea aplicatiei. Presupune rularea registrului RMI, a serverelor si a
clientilor.
2015

Proiectarea unui motor generic de calcul

• Se considera o AOD ce implementeaza un motor generic de


calcul – MGC. MGC este un OD gazduit pe server ce primeste
sarcini de calcul de la clienti, le executa si intoarce rezultatele
acestora. MGC permite unuia sau mai multor clienti sa
acceseze resursele unei masini mai puternice ce poate avea
acces la resurse hardware specializate.
• Aspectul inovativ al MGC este ca sarcinile nu trebuie definite
cand MGC este implementat si pornit. Se pot crea noi tipuri de
sarcini ce pot fi livrate spre executie catre MGC. Singura
restrictie este ca sarcinile sa implementeze o anumita interfata.
Codul necesar pentru rularea sarcini poate fi descarcat dinamic
de catre sistemul RMI. Ulterior, codul poate fi rulat de masina
gazda a MGC.
2015
Sarcini generice de calcul

• Abilitatea de a executa sarcini generice este obtinuta


prin:

– i) natura dinamica a platformei Java, ce permite incarcarea


dinamica a claselor;

– ii) extensia modelului obiectual pentru retele prin RMI. In


acest fel MGC poate descarca dinamic si apoi rula codul
unei sarcini de calcul, fara sa fie nevoie sa cunoasca
dinainte (de exemplu de la compilare) clasa ce contine acel
cod.
2015

Proiectarea ID a MGC

• MGC preia sarcini de la clienti, le executa si intoarce rezultatul clientilor.


• ID a MGC defineste o singura metoda pentru trimiterea spre executie a
unei sarcini. O sarcina de executie este un tip parametrizat Task<T> unde
T este tipul rezultatului sarcinii de calcul.
package compute;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Compute extends Remote {
<T> T executeTask(Task<T> t) throws RemoteException;
}
• Interfata unei sarcini defineste o metoda pentru executia sarcinii:
package compute;
public interface Task<T> {
T execute();
}
2015
Transferul parametrilor I
• Java RMI foloseste mecanismul de serializare Java pentru transportul
obiectelor intre JVM diferite in cazul apelurilor la distanta.
• Un obiect este considerat serializabil daca implementeaza interfata
java.io.Serializable.
– Clasele care implementeaza interfata Task vor trebui sa implementeze si interfata
java.io.Serializable pentru a putea fi transmise ca parametru metodei executeTask().
– Acelasi lucru este valabil si pentru obiectele rezultat (corespunzatoare tipului generic
T), deoarece ele sunt intoarse ca rezultat de metoda executeTask().
• Orice sarcina ce implementeaza interfata Task poate fi transmisa spre
executie catre MGC. O astfel de clasa poate contine si alte date necesare
pentru executia sarcinii, cat si alte metode necesare in cadrul executiei.
• Implementarile unor obiecte Task vor putea fi descarcate de Java RMI in
JVM unde ruleaza MGC. In acest fel clientii vor putea defini noi sarcini
ce pot fi executate pe calculatorul MGC fara a fi nevoie de codul acestor
clase instalat pe acest calculator.
• Transferul unei sarcini catre MGC se face cu metoda executeTask(),
disponibila tuturor clientilor pentru apel la distanta..
2015

Transferul parametrilor II
• Argumentele si valorile returnate ale metodelor la distanta pot fi de
urmatoarele tipuri: obiecte locale, OD, tipuri primitive, etc. Obiectele
locale trebuie sa fie serializabile.
• Regulile de transfer sunt urmatoarele:
– OD sunt transmise in general prin referinta – ROD. Pe partea de client o ROD
desemneaza obiectul stub asociat OD respectiv.
– Obiectele locale sunt transmise prin valoare, folosind serializarea obiectelor. Se
copiaza implicit toate campurile, exceptand campurile static si transient.
• Transferul unui OD prin ROD inseamna ca orice modificare a starii OD
prin invocarea unei metode la distanta se va reflecta in OD. Cand se
transmite un OD, numai metodele definite de ID sunt disponibile la
receptor. Celelalte metode din implementarea clasei obiectului nu sunt
disponibile receptorului.
• In schimb transferul unui obiect local presupune transferul prin valoare,
fiind creata o copie a obiectului la receptor. Astfel ca orice schimbare a
obiectului la receptor nu se va reflecta in originalul copiei la expeditor.
2015
Implementarea unei ID
• O clasa ce implementeaza una sau mai multe ID-uri trebuie in general sa
realizeze urmatoarele:
– Sa declare ce ID-uri implementeaza
– Sa defineasca cate un constructor pentru fiecare OD
– Sa furnizeze cate o implementare pentru fiecare dintre metodele din ID-urile
implementate
• Un program server RMI trebuie sa creeze o multime de OD-uri initiale si
sa le ‘exporte’ in cadrul sistemului RMI. Acest lucru inseamna ca ele vor
fi disponibile invocarii la distanta.
• Procedura de initializare - setup poate fi incapsulata intr-una dintre
metodele implementare clasei unui OD sau poate fi inclusa intr-o alta
clasa. Ea trebuie sa realizeze urmatoarele:
– Sa creze si sa instaleze un manager de securitate
– Sa creeze si sa ‘exporte’ unul sau mai multe OD-uri
– Sa inregistreze cel putin un OD in registrul RMI (sau intr-un alt serviciu de nume,
cum ar fi un serviciu accesibil prin Java Naming and Direcory Interface – JNDI)
pentru
2015

Implementarea MGC I
package engine;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import compute.Compute;
import compute.Task;

public class ComputeEngine implements Compute {

public ComputeEngine() {
super();
}

public <T> T executeTask(Task<T> t) {


return t.execute();
}
...
2015
Implementarea MGC II
...
public static void main(String[] args) {
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
try {
String name = "Compute";
Compute engine = new ComputeEngine();
Compute stub =
(Compute)UnicastRemoteObject.exportObject(engine, 0);
Registry registry = LocateRegistry.getRegistry();
registry.rebind(name, stub);
System.out.println("ComputeEngine bound");
} catch (Exception e) {
System.err.println("ComputeEngine exception:");
e.printStackTrace();
}
}
}

2015

Initializarea serverului RMI I


• Pasul 1: se instaleaza un manager de securitate (engl.security manager) ce
protejeaza accesul la resursele sistemului de un eventual cod de
‘neincredere’ (engl.untrusted) descarcat in cadrul JVM. Un manager de
securitate are rolul de a determina daca codul descarcat poate accesa
sistemul local de fisiere sau poate executa alte operatii privilegiate.
• Daca nu se instaleaza un manager de securitate atunci RMI nu va putea
descarca clase dinamic de la alta locatie decat calea locala catre fisierele cu
clase – classpath pentru obiectele primite ca argumente sau returnate de
invocari la distanta. In acest fel se asigura faptul ca operatiile realizate de
codul descarcat sunt conforme cu o politica de securitate.
• Pasul 2: se creaza o instanta a clasei ComputeEngine si se exporta aceasta
instanta in sistemul RMI pentru a fi disponibila pentru apeluri la distanta.Al
doilea argument (de tip int) al metodei exportObject() specifica optional un
port pe care se asculta invocarile la distanta ale OD-ului respectiv. Daca se
specifica valoarea 0 (ca in exemplu) atunci portul este anonim. Apelul de
‘export’ returneaza o ROD la OD creat. Tipul sau va fi Compute (adica ID),
si nu clasa care implementeaza aceasta ID (ComputeEngine in acest caz).
2015
Initializarea serverului RMI II
• Pasul 3: Se creaza un nume extern pentru OD, “Compute” in acest caz.
Apoi se inregistreaza OD creat sub acest nume in registrul RMI.
• Registrul RMI este un tip special de OD care se foloseste pentru a
determina referinte la alte OD. De obicei el se foloseste pentru localizarea
unui singur OD prin intermediul caruia se vor determina alte referinte la
OD-uri disponibile.
• Interfata java.rmi.registry.Registry defineste interfata pentru inregistrarea
si regasirea OD-urilor in registrul RMI.
• Pentru sintetizarea unei ROD la un registru RMI aflat la o adresa
particulara (adresa IP si port) se foloseste clasa
java.rmi.registry.LocateRegistry.
• Invocarea metodei statice getRegistry() a clasei LocateRegistry are ca
efect sintetizarea unei ROD la un registru RMI aflat pe calculatorul local
si conectat la portul implicit 1099.
• Invocarile registrului RMI primesc ca parametru ROD ale obiectelor
cautate respectiv inregistrate.
• Din motive de securitate, o aplicatie poate inregistra obiecte (bind,
unbind, rebind) doar intr-un registru ce ruleaza pe acelasi calculator. 2015

Crearea programului client


• In cazul nostru trebuie sa implementam doua clase pe partea de client:
– Clasa ComputePi determina OD si invoca sarcina de calcul a lui π.
– Clasa Pi care calculeaza pe π cu un numar prestabilit de zecimale.
• Schema de lucru a programului principal corespunzator clasei ComputePi este urmatoarea:

• Pasii de lucru ai clientului sunt:


– Instalarea unui manager de securitate. Acest pas este necesar deoarece receptionarea unei ROD
poate necesita descarcarea unor clase de pe server.
– Determinarea numelui OD. In exemplul nostru se foloseste numele “Compute”.
– Determinarea unui OD corespunzator registrului RMI asociat calculatorului ce gazduieste OD.
Se foloseste metoda LocateRegistry.getRegistry(host).
– Regasirea OD folosind registrul RMI cu metoda lookup(name) a clasei Registry.
– Crearea sarcinii de calcul, o instanta a clasei Pi in acest caz. Argumentul constructorului indica
numarul de zecimale.
– In final se transfera sarcina spre executie OD-ului ce reprezinta motorul de calcul, folosind
metoda executeTask(task).
2015
Observatii asupra programului client
• Toate clasele serializabile trebuie sa declare un camp private static final
long serialVersionUID pentru a garanta compatibilitatea la
serializare/deserializare intre diversele versiuni ale clasei respective.
• Se observa ca OD ce implementeaza interfata Compute nu are nevoie sa
cunoasca dinainte codul clasei Pi pana cand un obiect instanta a clasei Pi
este transmis ca parametru al metodei executeTask(). In acel moment
codul clasei Pi este incarcat in JVM-ul corespunzator motorului de calcul
si apoi se invoca metoda execute() asupra obiectului transmis ca
parametru ce reprezinta sarcina de calcul a lui π.
• Rezultatul executiei sarcinii este in acest caz un obiect BigDecimal ce se
transmite ca rezultat clientului.
• In concluzie, din punctul de vedere al motorului de calcul, este nerelevant
faptul ca sarcina transmisa ca parametru calculeaza valoarea lui π.
Aceasta tehnica se putea folosi la fel de bine pentru determinarea unui
numar prim foarte mare folosind spre exemplu un algoritm probabilistic.
In acest caz executarea sarcinii ar presupune incarcarea altei clase
corespunzatoare acestei sarcini de calcul. 2015

Compilarea unei aplicatii Java RMI


• Primul pas este construirea unei biblioteci JAR care sa contina codul
interfetelor Compute si Task. Aceste interfete sunt necesare:
– Clientului, care va utiliza interfata Compute pentru accesul la OD si va implementa
interfata Task pentru crearea sarcinii de calcul a lui π
– Serverului care va implementa interfata Compute si va executa sarcinile primite
folosind interfata Task.
• Pentru aceasta se compileaza sursele celor doua interfete si se
construieste bibilioteca JAR.
cd c:\__users\Lucru\workshops\InterfataCompute\src
javac compute/*.java
jar cvf compute.jar compute/*.class
• Rezulta fisierul compute.jar care se distribuie in subdirectoarele lib ale
proiectelor RMIClient si RMIServer.
• Compilarea celor doua proiecte presupune intai adaugarea la fiecare
proiect in parte a bibliotecii compute.jar.
• In versiunile JDK inaintea versiunii 5.0 era nevoie de un pas suplimentar
pentru determinarea claselor stub cu compilatorul rmic. Incepand cu
versiunea 5.0 acest pas nu mai este necesar.
2015
Manageri de securitate
• Ambele aplicatii client si server au instalat cate un manager de securitate.
Din acest motiv fiecare trebuie sa specifice cate o politica de securitate
descrisa printr-un fisier special.
• Politica de securitate descrie drepturile de executie pe care le are un
anumit in functie de provenienta sa. In aplicatia noastra se dau toate
drepturile posibile codului local, si nici o permisiune codului descarcat
dintr-o alta sursa. Efectul este ca MGC restictioneaza codul sarcinilor de
calcul primite de a putea executa operatii ce ar necesita permisiuni
speciale de securitate.
• Spre exemplu, codul sarcinii Pi nu necesita nici o permisune de securitate
speciala pentru a putea fi executat.
grant codeBase "file:C:/__users/Lucru/workshops/RMIServer/bin/" {
permission java.security.AllPermission;
};

grant codeBase "file:C:/__users/Lucru/workshops/RMIClient/bin/" {


permission java.security.AllPermission;
};
2015

Rularea unei aplicatii Java RMI


• Pasii sunt urmatorii:
– Se porneste registrul RMI. Acesta permite unui client sa obtina o referinta initiala la un
OD.
– Se porneste serverul
– Se porneste clientul
• Pornirea registrului RMI:
start rmiregistry
• Pornirea serverului:
java -cp .;../lib/compute.jar
-Djava.rmi.server.codebase=file:/C:/__users/Lucru/workshops/RMIServer/lib/compute.jar
-Djava.rmi.server.hostname=Toshiba
-Djava.security.policy=server.policy
engine.ComputeEngine
• Proprietatea codebase defineste o sursa sau locatie de unde se pot incarca
clase intr-un JVM. Variabile CLASSPATH defineste un codebase local, in
sensul ca defineste una sau mai multe cai din sistemul local de fisiere de
unde se pot incarca clase.
• Pornirea clientului:
java -cp .;../lib/compute.jar
-Djava.rmi.server.codebase=file:/c:/__users/Lucru/workshops/RMIClient/bin/
-Djava.security.policy=client.policy
client.ComputePi Toshiba 45
2015
Tehnologii de baza pentru SD bazate
pe Web

Capitolul 7

2015

World Wide Web – Web sau WWW


• Web-ul este un sistem hipermedia distribuit. Se bazeaza
pe un model de structurare a documentelor ce foloseste
trei concepte:
– Multimedia – se refera la integrarea mai multor tipuri de
media in cadrul aceluiasi model de document: text, grafica,
imagine, video, etc.
– Hiperdocument – se refera la crearea de legaturi intre
documente, folosind un mecanism propriu modelului de
document.
– Documente distribuite – se refera la documente care contin
legaturi la documente stocate pe alte calculatoare din cadrul
unei retele.
2015
Web: documente hipermedia distribuite
• Web-ul foloseste un model de documente hipermedia distribuite.
Hipermedia inglobeaza
– Multimedia
– Hiperdocument.
• Fiecare autor care creaza o resursa informationala (engl.information
resource) in Web o considera ca fiind un document separat.
• La nivel global, multimea tuturor resurselor informationale din Web
formeaza un unic document hipermedia distribuit. Din acest punct
de vedere, termenul de resursa informationala este mai potrivit
decat document.
• Exista trei nivele de distribuire a resurselor informationale in Web:
– acelasi fisier
– fisiere separate pe acelasi calculator
– fisiere separate pe calculatoare diferite.
2015

Portiune din Web

http://www.google.comlsearch?q=kindberg
www.google.com

Web servers Browsers

www.cdk3.net Internet
http://www.cdk3.net/

www.w3c.org

File system of http://www.w3c.org/Protocols/Activity.html


www.w3c.org Protocols

Activity.html

2015
Standarde Web
• Sunt specificatii formale si tehnice non-
proprietare ale diverselor aspecte ale Web-ului.

• Ele sunt definite si promovate de comitete de


standardizare (engl. standardization body) :
– World Wide Web Consortium (W3C)
– Internet Engineering Task Force (IETF)
– International Organization for Standardization (ISO)
– European Computer Manufacturers Association
(ECMA international)

• Specificatiile W3C pot avea constrangeri diverse:


– recomandari (definitive, candidate, propuse)
– documente de lucru (engl. working draft)

2015

Arhitectura Web-ului
• Este o arhitectura client/server tipica.
– Un server Web are sarcina de a gestiona o multime de
documente din cadrul Web. Aceste documente se numesc si
pagini Web.
– Un client generic de Web este un program care emite cereri
catre un server Web pentru accesarea paginilor Web
gestionate de acel server. Exemple de clienti sunt:
• Un navigator WWW care permite regasirea si afisarea paginilor
WWW in scopul vizualizarii continutului lor de catre un agent
uman.
• Un program de tip softbot care localizeaza diverse pagini WWW
in scopul crearii unui index. Indexul poate fi utilizat ulterior de un
motor de cautare.
2015
Web – concepte de baza
• Conceptele de baza ale Web-ului:

– Schema de numire a resurselor


(engl.uniform resource locator) URL

– Protocolul de transfer al
documentelor (engl. hypertext
transfer protocol) HTTP

– Limbajul de reprezentare a
continutului paginilor Web (engl.
hypertext markup language) HTML
2015

Identificarea resurselor in Web


• Pentru identificarea resurselor Web se foloseste un URL (engl. Uniform
Resource Locator). Un URL este un identificator simbolic al resursei si
este compus din doua parti:
– Schema, care indica modalitatea folosita pentru denumirea resurselor. Spre
exemplu, schema poate fi numele unui proocol: ftp, http, etc
– Partea specifica schemei, care indica cum se adreseaza resursa in cadrul schemei
• Sintaxa URL este schema “:” parte-specifica-schemei. Partea specifica
schemei are sintaxa “//” [utilizator [“:” parola] “@” ] gazda [ “:” port]
“/” cale
– utilizator si parola sunt optionale si se aplica doar cu schemele care au sens (de
exemplu ftp).
– gazda indica numele calculatorului pe care se afla resursa, sau adresa sa de IP.
– port reprezinta numarul portului pe care se face conexiunea. Este optional,
deoarece acest numar este predefinit pentru serviciile standard. Pentru HTTP portul
predefinit este 80.
– cale reprezinta calea de acces la resursa din cadrul calculatorului specificat. In
general este o cale fizica existenta in sistemul de fisiere de pe calculatorul gazda.
2015
URN
• URN (engl. uniform resource name) reprezinta un nume
simbolic unic atasat unei resurse Web.
• Un exemplu de URN in afara contextului Web este ISBN-ul
unei carti:
ISBN 0-486-27557-4 (urn:isbn:0-486-27557-4)
• Un exemplu in Web este DOI (engl. digital object identifier).
El este un identificator pentru identificarea unica a unui
document electronic (articol sau carte). Este folosit de
bibliotecile digitale online.
• Un exemplu de DOI in web este:
doi:10.1000/182
• El se poate transforma intr-un URL prin adaugarea unui prefix
Web, astfel:
– http://dx.doi.org/10.1000/182 2015

Istoric HTTP
• Este protocolul de comunicare intre clientii si serverele Web. Specifica
cererile care pot fi adresate de clienti si raspunsurile care pot fi generate
de servere. Specificatia defineste structura si formatul (sintaxa) acestora.
• HTTP/0.9 (versiunea initiala), inainte de raspandirea WWW, foarte
limitata. Singura cerere admisa este GET, la care serverul raspunde cu
documentul cerut.
• HTTP/1.0 (1992), este un document informativ, nu un standard. Foloseste
conceptul de tip media (MIME). S-au introdus noi cereri, de exemplu
cererea POST pentru trimiterea de date de la client catre server.
• HTTP/1.1 (1997). Inlatura problemele versiunii anterioare: i) modelul
interactiunii unice cerere/raspuns pe conexiune TCP/IP, model care are
performante slabe. Aceasta versiune introduce conexiunile persistente; ii)
lipsa de suport pentru gazdele virtuale non-IP. Conceptul de gazda
virtuala (engl.virtual host) permite unui server WWW sa deserveasca
cereri catre mai multe calculatoare gazda. In HTTP/1.1 este posibil sa se
specifice explicit in cererea HTTP calculatorul gazda careia ea ii este
adresata rezultand astfel conceptul de gazda virtuala non-IP.
2015
HTTP – protocol cerere-raspuns
• HTTP = protocol de aplicatie de tip cerere-raspuns (engl.request-reply).
• Protocoalele de aplicatie faciliteaza comunicatia intre componentele unei
aplicatii distribuite. Exemple: SMTP, IMAP, POP3, etc.
• Conform modelului cerere-raspuns, un proces client emite cereri catre un
proces server. Procesul server proceseaza cererea si intoarce un raspuns.
• Se mai numeste model pull, prin contrast cu un model push in care
clientul este instiintat automat de schimbarile de stare ale serverului.
• Cererile si raspunsurile HTTP se mai numesc si mesaje. Un mesaj este un
sir de caractere ce contine: linia de start (engl.start line), zero sau mai
multe campuri antet (engl.message header field) si optional un camp
corp (engl.message body field).
• Cererile contin informatii de identificare a tipului entitatilor. Se foloseste
formatul MIME (Multipurose Internet Mail Extensions). Untip MIME
specifica un tip si un subtip, de exemplu: text/plain, text/html,
image/jpeg, etc.
2015

Cereri si raspunsuri HTTP I


• Antetele unui mesaj pot fi: antete generale (engl.general
header) – se refera la mesaj, nu la entitatea transmisa; antete
de entitate (engl.entity header) – se refera la entitatea
transmisa sau referita; antete raspuns (engl.response header) –
serverul comunica clientului informatii care nu au fost incluse
in linia de start.
• Se pot transmite manual cereri catre un server de Web folosind
telnet.
• Cereri – Linia de start se numeste linie de cerere (engl.request
line) si are structura:
metoda spatiu url_resursa spatiu versiune_http sfarsit_linie
GET /staff/badica/index.html HTTP/1.1
Connection: Keep-Alive
Host: www.dcs.kcl.ac.uk
Accept: text/html
2015
Cereri si raspunsuri HTTP II
• Raspunsuri – Linia de start se numeste linie de stare
(engl.status line).
HTTP/1.1 200 OK
Date: Thu, 01 Aug 2002 16:03:06 GMT
Server: Apache/1.3.20 (Unix) PHP/4.0.3pl1 mod_perl/1.26
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html

2d8
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
....
</html>

2015

Sintaxa formala a unei cereri HTTP


• HTTP 1.0 este descris la nivel informativ in documentul RFC 1945.
• HTTP 1.1 este descris in propunerea de standard RFC 2068.
• O cerere HTTP are structura urmatoare ([...] specifica un element
optional si * specifica 0 sau mai multe repetitii ale unui element):

cerere =
linie-de-cerere
(antet-general | antet-cerere | antet-entitate)*
sfarsit-de-linie
[corp-mesaj]
linie-de-cerere = metoda spatiu uri spatiu versiune-http sfarsit-de-linie
metoda =
OPTIONS | GET | HEAD | POST | PUT | DELETE |
TRACE | CONNECT | metoda-extensie
uri = * | uri-absolut | cale-absoluta
2015
Sintaxa formala a unui raspuns HTTP
Un raspuns HTTP are structura urmatoare: eroare-client = cerere-gresita | neautorizat |
raspuns = plata-necesara | interzis |
linie-de-stare resursa-inexistenta | metoda-nepermisa | ...
(antet-general | antet-raspuns | antet-entitate)* cerere-gresita = 400
sfarsit-de-linie neautorizat = 401
[corp-mesaj] plata-necesara = 402
linie-de-stare = versiune-http spatiu cod-stare interzis = 403
spatiu fraza-motiv sfarsit-de-linie resursa-inexistenta = 404
cod-stare = cod-succes | redirectare | metoda-nepermisa = 405
eroare-client | eroare-server | ...
eroare-server = eroare-interna | nu-este-
cod-succes = ok | creat | acceptat | ... implementata | ...
ok = 200 eroare-interna = 500
creat = 201 nu-este-implementata = 501
acceptat = 202
redirectare = mutat-permanent | mutat-temporar
| ...
mutat-permanent = 301
mutat-temporar = 302
2015

Cookies
• HTTP este un protocol fara stare (engl.stateless). HTTP nu dispune de
un mecanism propriu care sa permita unui server Web sa poata pastra
informatii despre starea clientului.
• Termenul de cookie se refera la mecansimul prin care o aplicatie Web pe
partea de server poate stoca si regasi informatii despre starea unui client.

• Serverul specifica clientului ca vrea sa stocheze un cookie prin antetul Set-Cookie, in


maniera urmatoare:
Set-Cookie: Nume=Valoare
• Ulterior, clientul va include cookie-ul intr-un antet al unei cereri sub forma:
Cookie: Nume=Valoare
• Suplimentar, antetul Set-Cookie mai poate contine urmatoarele informatii:
– domain: specifica domeniul in care se aplica cookie-ul
– expires: specifica data de expirare a cookie-ului
– path: specifica URL-urile la care clientul va returna cookie-ul in cererea HTTP
– secure: specifica faptul ca cookie-ul va fi returnat de client numai daca conexiunea este
sigura.
Ex: Set-Cookie: Credit=111; secure; expires=Thursday, 07-Dec-2000,
10:00:00 GMT; domains=.comp-craiova.ro; path=/
2015
HTML – Istoric I
• HTML 2.0, standardul fiind fost propus in 1995 cu scopul de a
colecta intr-un unic document toate capabilitatile HTML
existente in practica inainte de 1994.
• HTML 3.2, descris intr-o recomandare W3C din 1997 cu
scopul de a prezenta consenul privind facilitatile HTML
existente pana in 1996. Extinde HTML 2.0 cu noi facilitati ca:
tabele, miniaplicatii (engl.applet), mixarea armonioasa a
textului si imaginii, etc., pastrandu-se in acelasi timp
compatibilitatea inapoi.
• HTML 4.0, descris intr-o recomandare W3C de la sfarsitul din
1997, revizuita la inceputul lui 1998. Extinde HTML 3.2 cu
noi facilitati pentru multimedia, scripting, foi de stiluri
(engl.style sheets), internationalizare, acces pentru utilizatorii
cu dizabilitati, etc. HTML 4.0 a fost inlocuit la sfarsitul lui
1999 cu HTML 4.01. 2015

HTML – Istoric II
• XHTML 1.0, este o reformulare a HTML 4.01 ca aplicatie XML intr-o
recomandare W3C de la inceputul lui 2000. La inceputul lui 2001
XHTML 1.1 extinde XHTML 1.0 cu facilitati pentru modularizare.
• Incepand cu 2003 s-a lucrat la specificatia XForms pentru specificatia
formularelor Web.
• Ulterior a aparut ideea preluarii ideilor XForms in HTML. Dar aceasta
idee a fost initial rejectata de W3C, ca fiind in conflict cu directia
dezvoltarii formularelor Web bazate pe XML.
• Cu toate acestea, ideea a fost continuata de implementatorii de
navigatoare (Opera, Mozzila, Apple).
• In 2006 W3C a reluat ideea dezvoltarii HTML, iat in 2007 a fost creat un
grup W3C responsabil cu dezvoltarea HTML 5.0 (sau HTML5).
• In februarie 2014 a fost publicata o recomnadere candidat W3C pentru
HTML5.

2015
HTML – Concepte
• Lingua franca pentru hipertext in Web.
• HTML este inspirat din SGML. SGML a fost
inventat in 1986 (mult inainte de aparitia Web).
• SGML este un limbaj de meta-marcare (engl.meta-markup). In
esenta el permite definirea de noi tipuri de documente printr-o
definitie de tip de document – DTD. Unui tip ii corespunde un
limbaj de marcare specific (ex. HTML). El descrie continutul
si structura unui document. Un document scris intr-un limbaj
de marcare contine:
– Date = continutul propriuzis al documentului.
– Marcaje = informatii referitoare la structura documentului.
Se numesc si metadate.
• XML este un limbaj de meta-marcare inspirat tot de SGML.
2015

HTML 4.0
• Pentru a sprijini si versiunile mai vechi de HTML, versiunea 4.0 defineste 3
tipuri de documente HTML:
– Documente tranzitionale: acest tip se va folosi doar pentru verificarea
documentelor HTML, in nici un caz pentru generarea de noi documente.
Astfel, elemente ca BASEFONT, FONT, CENTER, S, STRIKE sau U sunt
doar parte a documentelor tranzitionale. Ele sunt folosite pentru formatare.
In viitor formatarea se va face cu foi de stiluri CSS.
– Documente stricte: acest tip nu include elementele prezente in documentele
tranzitionale pentru compatibilitate cu versiunile anterioare de HTML.
– Documente tip colectii de pagini
• Tipul de document se defineste printr-o definitie de tip (concept preluat din
SGML). Definitia de tip se specifica optional la inceputul unui document
HTML astfel:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3c.org/TR/REC-html40/strict.dtd">

2015
Structura unui document HTML
• Un document HTML contine date si marcaje (engl.tag). Marcajele contin
informatia de formatare (pentru programul navigator), iar datele reprezinta
continutul documentului. Ele determina modul de afisare a datelor.
Marcajele pot fi: de inceput (engl.start tag) si de sfarsit (engl.end tag).
• Un marcaj de inceput poate contine optional atribute cu valori astfel:
<marcaj atribut = ”valoare” atribut = ”valoare” …>
Ex: <img src= ”logo.gif” alt=”home page” >
• Un marcaj de sfarsit se scrie astfel:
</marcaj>
Ex: </img>
• Teoretic marcajele trebuie inchise corect, ca parantezele unei expresii
matematice. In practica, deseori, marcajele de sfarsit se omit, ambiguitatile
fiind rezolvate prin metode ad-hoc de programul navigator. Astfel ca
HTML4 s-a redefinit in XML rezultand XHTML. In XML un document
este bine-format (engl.well-formed), cu marcajele inchise corect.
• Un document HTML contine un antet (engl.header) si un corp (engl.body)
intre marcajele <html> si </html>. html este elementul radacina.
2015

Clasificarea elementelor HTML


• Elemente nivel bloc (engl.block-level). Ex: P, H, UL, OL, PRE, TABLE,
FORM, ...
• Elemente incluse (engl.inline). Ex: I, B, U, EM, STRONG, A, IMG, ...
• Diferentele exista pe 3 coordonate: continut, formatare si directionalitate.
• Continut:
– Un element de nivel bloc poate contine elemente incluse si elemente de nivel bloc.
– Un element inclus poate contine numai elemente incluse si date.
– Aceasta distinctie sugereaza ca elementele de nivel bloc pot crea structuri mai bogate
decat elementele incluse.
• Formatare:
– Elementele de nivel bloc sunt formatate intotdeauna incepand cu o linie noua, in timp
ce elementele incluse nu.
– Elementele incluse pot fi despartite pe mai multe linii (la fel cum textul unui paragraf
se desparte in linii), in timp ce elementele de nivel bloc nu.
• Directionalitate (se refera la directia in care este scris textul):
– Elementele de nivel bloc mostenesc directionalitatea de la elementul cuprinzator, in
timp ce elementele incluse nu.
2015
Un exemplu de document HTML
<HTML>
<HEAD>
<TITLE> Un exemplu simplu de pagina WWW </TITLE>
</HEAD>
<BODY>
<H1> Costin Badica despre HTML </H1>
Un document HTML contine:
<UL> html
<LI> marcaje - marcajele pot fi:</LI>
<UL>
<LI>marcaje de inceput</LI> head body
<LI>marcaje de sfarsit</LI>
</UL>
<LI> date </LI>
</UL> title h1 ... ul ... ul
si este compus din:
<UL> ...
<LI> un antet </LI>
<LI> un corp </LI>
Structura interna a unui document HTML are
</UL> forma unui arbore. Nodurile arborelui se numesc
</BODY> elemente.
</HTML>
2015

Formatarea textului in HTML


• Textul HTML poate fi simplu sau structurat.
• Textul simplu este format din paragrafe (p), separate de linii libere (br) sau
titluri (engl.headings, h1, h2,…, h6). Textul poate avea stiluri (ex. bold b,
italic i, etc), fonturi (font, basefont)
• Textul structurat cuprinde liste si tabele.
• Listele sunt: liste neordonate (ul, li) cu elementele indicate cu simboluri
nenumerice (engl.bullet), liste ordonate (ol, li) cu elementele numerotate, si
liste de definitii (dl, dd) cu simbolurile elementelor definite de utilizator.
• Tabelele (table) permit structurarea textului in linii si coloane. In principiu
un tabel contine unul sau mai multe corpuri de tabel (engl.table body, tbody).
Un corp de tabel contine una sau mai multe linii (engl.row, tr). O linie este
formata din celule. Acestea pot fi celule antet (engl.header cell, th) sau celule
de date (engl.data cell, td).
• Pentru tabele exista si alte elemente si atribute optionale care specifica titlul
tabelului (caption), alinierea celulelor (align), stilul conturului (border),
formatarea textului in celule, etc. Spre exemplu stilul (grosimea) conturului se
specifca astfel: <table border=”1”>.
2015
Un exemplu de tabel HTML
<TABLE BORDER ="2">
<CAPTION>Tabelul</CAPTION>
<TBODY>
<TR>
<TH>1</TH>
<TH>2</TH>
</TR>
<TR>
<TD>1</TD>
<TD>2</TD>
</TR>
<TR>
<TD>Linie</TD>
<TD>Linie</TD>
</TR>
</TBODY>
<TBODY>
<TR>
<TD>Alta linie</TD>
</TR>
</TBODY>
</TABLE> 2015

Legaturi HTML
• Se bazeaza pe folosirea de ancore (engl.anchor) cu elementul a. Exista
doua tipuri de ancore: ancore sursa si ancore destinatie.
• Ancorele sursa au forma
<a href=”url”>text</a>
si reprezinta originea unei legaturi. url reprezinta resursa destinatie a
legaturii. text este textul afisat in zona sensibila a legaturii.
• Ancorele destinatie au forma
<a name=”nume”></a>
si reprezinta destinatia unei legaturi. Numele unei ancore destinatie
poate fi specificat intr-o ancora sursa prin #nume pe post de url.
Ancorele destinatie se pot specifica si cu atributul id in cadrul
elementului referit, in acest caz numai fiind nevoie sa se foloseasca
elementul a.

2015
Paginile Web statice si dinamice

• Paginile Web pot fi statice si dinamice.


• Paginile statice sunt stocate pe server si returnate
clientilor ca raspuns la cereri GET.
• Paginile dinamice sunt generate dinamic de server,
nefiind stocate explicit. Este posibil ca aceste pagini sa
fie configurate pe baza unor date trimise de la client
catre server. Astfel de date pot fi de exemplu criterii de
cautare intr-o baza de date, paginile generate dinamic
fiind in acest caz rapoartele rezultate in urma cautarii.

2015

Trimiterea de date catre un server Web


• Exista doua metode de a transmite date de la client la server:

– Folosind metoda GET, datele sunt atasate URL-ului sub forma unor perechi
variabila-valoare. In acest caz URL-ul reprezinta un program aflat pe server si datele
sunt transmise acestui program in mediul sau de executie (engl.environment). La
URL se adauga un sir de forma:
?nume1=valoare1&nume2=valoare2& … &numen=valoaren
Un caracter special printr-un cod hexa precedat de ’%’. Ex. ?cale=%2Fweb%2
semnifica valoarea /web/ pentru variabila cale.

– Folosind metoda POST, datele sunt atasate in corpul cererii, spre deosebire de cazul
anterior, unde sunt atasate URL-ului, in antet. Ele sunt transmise programului prin
intrarea standard.

• Serverul preia datele de la programul invocat prin iesirea standard si le


returneaza clientului. Tehnica de a extinde functionalitatea serverului
Web pentru generarea dinamica de pagini se numeste Common Gateway
Interface (CGI).
2015
Formulare HTML
• Formularele (engl.form) furnizeaza interactivitate paginilor Web. Ele se
specifica cu elementul form ce accepta atributele: action ce indica
programul de prelucrare a datelor formularului, method ce specifica
metoda HTTP folosita la transferul datelor catre server (GET sau POST),
target pentru a specifica fereastra ce contine formularul, etc.
• In interiorul elementului form se introduc elemente pentru descrierea
controalelor de interactivitate. Acestea pot fi:
– input, un element general cu tipul descris prin atributul type. Acesta poate fi:
text pentru o caseta de editare, password pentru o caseta de editare a unei
parole, checkbox pentru o caseta de validare, radio pentru un buton de selectie
exclusiva (engl.radio button), submit pentru un buton de trimitere a datelor catre
server, etc.
– select, pentru definirea unui meniu. Optiunile meniului se descriu cu elementele
option si optgroup. Meniul este cu selectie simpla sau multipla (multiple)
– textarea, pentru definirea unei camp de editare multilinie.
• Pentru vizualizarea datelor trimise la server se va implementa formularul
cu metoda GET si se va vizualiza URL-ul generat in campul de adresa al
navigatorului Web.
2015

Un exemplu de formular HTML (I)


<HTML>
<HEAD><TITLE> Un exemplu de formular </TITLE></HEAD>
<BODY>
<FORM METHOD ="GET">
<INPUT TYPE="TEXT" NAME="Nume" SIZE="15"></INPUT><P/>
<INPUT TYPE="PASSWORD" NAME="Parola" SIZE="6"></INPUT><P/>
<INPUT TYPE="CHECKBOX" NAME="Validare" CHECKED="on"></INPUT><P/>
<INPUT TYPE="RADIO" NAME="Grup" VALUE="1" CHECKED>1</INPUT>
<INPUT TYPE="RADIO" NAME="Grup" VALUE="2">2</INPUT><P/>
<INPUT TYPE="SUBMIT" NAME="Trimite" VALUE="Trimite"></INPUT><P/>
<INPUT TYPE="FILE" NAME="Poza" ACCEPT="image/gif" MAXLENGTH="40"
SIZE="12"></INPUT><P/>
<INPUT TYPE="HIDDEN" NAME="Secret" VALUE="Secret"></INPUT><P/>
<INPUT TYPE="BUTTON" NAME="Actiune" VALUE="Actiune"></INPUT><P/>
<INPUT TYPE="IMAGE" NAME="Imagine" VALUE="Imagine" SRC="tiny.jpg"></INPUT><P/>
<INPUT TYPE="RESET" NAME="Initializare" VALUE="Initializare"></INPUT><P/>
<TEXTAREA NAME="COMENTARIU" ROWS="6" COLS="10"></TEXTAREA><P/>
<SELECT NAME="OPTIUNI" SIZE="1">
<OPTION VALUE="Valoarea 1">Valoarea 1</OPTION>
<OPTION VALUE="Valoarea 2">Valoarea 2</OPTION>
</SELECT>
</FORM>
</BODY>
</HTML>
2015
Un exemplu de formular HTML (II)

2015

Un exemplu de formular HTML (III)


• Datele transmise de client serverului (partea de dupa ’?’ din URL)
pentru un scenariu de folosire a formularului prezentat arata astfel:

Nume=abc&
Parola=12ab&
Validare=on&
Grup=2&
Trimite=Trimite&
Poza=C%3A%5Cbackup%5Cpersonal%5CDarrelInceBook%5CCd+
Book%5Cindex.htm&
Secret=Secret&
COMENTARIU=comentariu&
OPTIUNI=Valoarea+2

• %3A este ’:’


• %5C este ’\’
• ’+’ este ’ ’ 2015
Comunicarea cu un server de Web
• Se considera o aplicatie pentru comunicarea cu un server de Web.
• Presupunem ca ne intereseaza doar simpla descarcare a unei pagini de la o
adresa data.
• Aplicatia va rula pe rol de client, asemanator cu un navigator de Web.
• Aplicatia realizeaza urmatorii pasi:
– Construieste un soclu conectat la URL-ul server-ului si portul corespunzator. Implicit
un server de Web asculta pe portul 80, dar se poate specifica si un alt port.
– Construieste o cerere GET de forma GET cale_resursa, unde cale_resursa reprezinta
numele resursei in sistemul de fisiere al serverului, relativ la o radacina implcita si o
transmite serverului.
– Receptioneaza raspunsul si il afiseaza (in cazul nostru afisarea se face la iseirea
standard).
– Inchide conexiunea prin inchiderea fluxurilor asociate conexiunii si a soclului asociat
conexiunii.
• Aceasta aplicatie va putea fi testata in doua ipostaze:
– Folosind unul dintre serverele disponibile in Web
– Folosind un server de Web de test, pe care il vom crea ulterior.
2015

Implementarea unui client simplu de HTTP - I


import java.io.*;
import java.net.*;
public class WebRetriever {
Socket soc;
OutputStream os; InputStream is;
WebRetriever(String server, int port) throws IOException,
UnknownHostException {
soc = new Socket(server, port);
os = soc.getOutputStream();
is = soc.getInputStream();
}
void request(String path) {
try {
String message = "GET " + path + "\n\n";
os.write(message.getBytes());
os.flush();
} catch (IOException e) {
System.err.println("Error in HTTP request");
}
}
2015
Implementarea unui client simplu de HTTP - II
void getResponse() {
int c;
try {
while ((c = is.read()) != -1)
System.out.print((char) c);
} catch (IOException e) {
System.err.println("IOException in reading from Web server: “
+ e.getMessage());
}
}

public void close() {


try {
is.close();
os.close();
soc.close();
} catch (IOException e) {
System.err.println("IOException in closing connection");
}
}
2015

Implementarea unui client simplu de HTTP - III

public static void main(String[] args) {


try {
// WebRetriever w = new WebRetriever("www.nus.edu.sg", 80);
// w.request("/NUSinfo/UG/ug.html");
// Din broswer: http://127.0.0.1:8080/exemplu.html
WebRetriever w = new WebRetriever("localhost", 8080);
w.request("/exemplu.html");
w.getResponse();
w.close();
} catch (UnknownHostException h) {
System.err.println("Hostname Unknown");
} catch (IOException i) {
System.err.println("IOException in connecting to Host");
}
}
}

2015
Utilizarea clientului de HTTP
• Clientul se poate rula considerand sintaxa simplificata a metodei GET:
GET /~badica_costin/proiecte/hiperproc/index_e.html
• si apoi considerand sintaxa completa:
GET /~badica_costin/proiecte/hiperproc/index_e.html HTTP/1.1
Connection: Keep-Alive
Host: software.ucv.ro
Accept: text/html
• Se observa ca in primul se livreaza direct continutul HTML al resursei.
• In al doilea caz apare un raspuns detaliat conform sintaxei raspunsurilor HTTP:
HTTP/1.1 200 OK
Date: Mon, 31 Mar 2008 15:50:50 GMT
Server: Apache/1.3.37 (Unix) mod_ssl/2.8.28 OpenSSL/0.9.8b PHP/4.4.4
Last-Modified: Thu, 23 Feb 2006 09:54:23 GMT
ETag: "9f41-1c78-43fd864f"
Accept-Ranges: bytes
Content-Length: 7288
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">


<html>
2015

Implementarea unui server de Web - I


• Se considera un server de Web foarte simplu ce recunoaste doar comenzi GET.
• Presupunem ca serverul determina resursa prin cautarea caii specificate in comanda
GET, relativ la directorul curent.
• Aplicatia va rula pe rol de server, similar cu un server de Web. Ne putem conecta la
server atat folosind un navigator Web, cat si aplicatia client prezentata anterior.
• Serverul realizeaza urmatorii pasi:
– Construieste un soclu de ascultare conectat la un port local, fie acesta portul 8080. Implicit un
server de Web asculta pe portul 80, dar se poate specifica si un alt port. In cazul folosirii pe
post de client.a unui navigator Web, portul trebuie specificat explicit in URL.
– Intr-o bucla infinita realizeaza pasii:
• Se accepta o conexiune de la un client.
• Se preia o cerere si se determina calea catre resursa. Cererea se considera incheiata la intalnirea unei
linii vide.
• Se returneaza resursa catre client.
• Se inchide conexiunea.
• Serverul se va putea fi testata in doua ipostaze:
– Folosind un navigator de Web. In acest caz trebuie specificat explicit portul 8080 in URL,
astfel: http://localhost:8080/exemplu.html sau http://127.0.0.1:8080/exemplu.html
– Folosind clientul creat anterior.

2015
Implementarea unui server de Web - II
import java.io.*;
public class WebServer {
Socket soc;
OutputStream os; BufferedReader is;
String resource;
void getRequest() {
try {
String message;
while ((message = is.readLine()) != null) {
if (message.equals(""))
break; // end of command block
System.out.println(message);
StringTokenizer t = new StringTokenizer(message);
String token = t.nextToken(); // get first token
if (token.equals("GET")) { // if token is ”GET”
resource = t.nextToken(); // get second token
System.out.println(resource);
}
}
} catch (IOException e) {
System.err.println("Error receiving Web request");
}
}
2015

Implementarea unui server de Web - III


void returnResponse() {
int c;
try {
FileInputStream f = new FileInputStream("."+resource);
while ((c = f.read()) != -1)
os.write(c) ;
f.close();
} catch (IOException e) {
System.err.println("IOException in reading in Web server");
}
}

public static void main(String args[]) {


try {
ServerSocket s = new ServerSocket(8080);
for (;;) {
WebServer w = new WebServer(s.accept());
w.getRequest();
w.returnResponse();
w.close();
}
} catch (IOException i) {
System.err.println("IOException in Server");
}
} 2015
Implementarea unui server de Web - IV
public void close() {
try {
is.close(); os.close(); soc.close();
} catch (IOException e) {
System.err.println("IOException in closing connection");
}
}

WebServer(Socket s) throws IOException {


soc = s;
os = soc.getOutputStream();
is = new BufferedReader(
new InputStreamReader(soc.getInputStream()));
}
}

2015

Servere Web
• Server Web = un program cu rol de server care este
capabil sa raspunda la cereri HTTP.
• Modul de functionare al unui server Web este foarte
important pentru infrastructura si aplicatiile Web, desi in
acelasi timp este ascuns utilizatorilor uzuali ai Web.
• Probleme importante referitoare la serverele Web sunt:
– Performanta
– Configurarea si administrarea
– Extensia si programarea
• Exemple de servere Web:
– Apache Tomcat (disponibil liber in domeniul public este) httpd
– MS Internet Information Services-IIS
2015
Functii de baza ale serverelor Web

2015

Performanta serverelor Web


• Parametrii de baza ai performantei unui server Web:
– Numar de cereri / secunda (in functie de tipul de cerere)
– Latenta = timp de raspuns in milisecunde pentru fiecare
conexiune sau cerere noua
– Rata de transfer (engl. throughput) in numar de octeti /
secunda in functie de dimensiunea paginilor, caching-ul
continutului, latimea de banda a retelei (engl. network
bandwidth).
• Instrumente pentru evaluarea performantei serverelor
Web:
– ApacheBench: http://en.wikipedia.org/wiki/ApacheBench
– http://en.wikipedia.org/wiki/Web_server_benchmarking

2015
Configuratii de servere Web
• Optiunile de configurare ale unui server Web se refera
in general la:
– Modul in care se va executa serverul pe masina care il
gazduieste:
• la cerere
• permanenta
– Daca serverul deserveste mai multe domenii folosind un
singur calculator si o singura adresa de IP. Aceste domenii
se numesc gazde virtuale (engl.virtual host).
– Modul de lucru:
• server de origine
• proxy

2015

Executia la cerere a serverelor Web


• Este o metoda mai veche. Presupune existenta unui
superserver care asculta toate cererile pe o multime de
porturi si pentru fiecare in parte activeaza si executa
serverul corespunzator. In UNIX acest superserver se
numeste inetd.
• Aceasta metoda are marele dezavantaj ca necesita
prea multe resurse sistem de fiecare data cand se
incarca serverul in memorie si se creaza procesul
aferent.
• Este utila pentru servicii care functioneaza la un nivel
scazut de incarcare.

2015
Executia permanenta a serverelor Web
• Serverul este pornit manual de utilizator sau automat
la pornirea sistemului si se executa in permanenta.
Dupa pornire serverul asculta cererile HTTP pe portul
pe care a fost configurat.
– Pornirea manuala este recomandata intr-un mediu de
dezvoltare a unei aplicatii Web.
– Pornirea automata este recomandata dupa ce aplicatia Web
a fost instalata (engl.deployed).
• Serverul poate fi pornit:
– de la linia de comanda sau
– instalat ca serviciu al sistemului de operare.

2015

Gazde virtuale
• Un server Web poate deservi unul sau mai multe
domenii numite gazde virtuale.

• Gazdele virtuale usureaza activitatea de administrare a


serverului deoarece: exista o singura instanta a
serverului, exista o singura configuratie a serverului,
se monitorizeaza executia unui singur server.

• Exista doua tipuri de gazde virtuale:


– gazde virtuale IP
– gazde virtuale non-IP.
2015
Gazde virtuale IP
• Fiecare gazda virtuala este o gazda IP avand o adresa
de IP distincta care apare ca intrare in DNS.

• Se asigneaza toate adresele de IP ale gazdelor virtuale


deservite masinii pe care ruleaza serverul Web.

• Metoda este simpla dar are doua dezavantaje: i) este


nevoie de o adresa de IP distincta pentru fiecare gazda
virtuala; ii) asignarea mai multor adrese de IP unei
singure masini poate crea probleme retelei.

2015

Gazde virtuale non-IP


• Gazde virtuale non-IP (sau bazata pe nume, engl. name-based):
– Se bazeaza pe un suport special oferit de protocolul HTTP. Acest
suport pentru deservirea gazdelor virtuale non-IP este disponibil numai
in HTTP/1.1.
– HTTP/1.1 a introdus in cadrul unei cereri HTTP antetul special HOST.
Acest camp antet este obligatoriu. El contine numele gazdei careia ii
este adresata cererea.
– Configurarea gazdelor virtuale deservite se face analog cu cazul
anterior. Singura diferenta este ca intrarile DNS ale gazdelor virtuale
vor contine acum aceeasi adresa de IP.
– Metoda are doua avantaje: i) este nevoie de o singura adresa de IP
pentru deservirea tuturor gazdelor virtuale; ii) crearea unei noi gazde
virtuale non-IP se poate face mai usor decat in cazul gazdelor virtuale
IP. Metoda are un dezavantaj: se poate aplica numai pentru versiunile
HTTP ulterioare HTTP/1.1 (nu mai este o problema la ora actuala).
2015
Servere de origine
• Majoritatea serverelor Web sunt configurate ca servere de origine. In acest
caz cererile HTTP sunt tratate local de server.
1: Cerere catre server
Client 2: Raspuns catre client Server de origine

• O problema importanta este localizarea resurselor, cu alte cuvinte maparea


URL-ului intr-o adresa a unei resurse din cadrul sistemului local de fisiere.
Resursele sunt de doua tipuri: statice (stocate fizic) si dinamice (generate
de programe externe).
• Spatiul Web al unui utilizator specific se refera in URL prin caracterul ~
urmat de numele utilizatorului. Spatiul Web al utilizatorilor se poate
organiza in doua moduri:
– Crearea unui spatiu Web central pentru toti utilizatorii. Unui utilizator ii va revni un
director in acest spatiu: webhome/name/.
– Crearea unui director special pentru fiecare utilizator in cadrul directorului personal:
/home/name/WWW/.
2015

Servere proxy
• Un server proxy accepta cereri pentru resurse si fie le rezolva din memoria
cache locala, fie prin inaintarea cererii catre serverul de origine.
1: Cerere catre proxy
Client 4: Raspuns catre client Proxy

2: Cerere catre 3: Raspuns catre


server proxy

Server de origine

• Un server proxy actioneaza astfel ca un intermediar intre client si serverul


de origine. Scopul intermedierii pote fi filtrarea cererilor sau trecerea de la
un protocol nesigur la un protocol sigur, de exemplu HTTPS.

2015
Tehnologii server pentru continut dinamic interactiv
• SSI
– Mecanism propriu serverului Web. Se refera la abilitatea de a modifica
dinamic continutul unei pagini folosind directive de preprocesare adresate
serverului. Ofera insa flexibilitate limitata.
• CGI
– Standard de comunicare intre un server de Web si un program extern. Acest
program extern poate fi scris in C, Perl, Python, etc.
• Miniserveri si JSP
– Extensii ale unui server Web bazate pe tehnologiile Java.
• ISAPI si ASP
– Extensii ale unui server de Web bazate pe tehnologiile Microsoft.
• PHP
– Limbaj de scripting pentru partea de server inspirat din Perl si C.

2015

Servere de aplicatii
• Aplicatiile de comert electronic au o parte semnificativa pe partea de
server. Pentru a descrie aceasta parte se foloseste frecvent termenul de
aplicatie Web = extensia dinamica a unui server Web.
• Aplicatiile Web sunt in general de doua tipuri:
– Aplcatii orientate pe prezentare. Contin pagini Web interactive si sunt capabile sa
genereze continut dinamic ca raspuns la cererile clientilor.
– Aplicatii orientate pe serviciu. Implementeaza un punct terminal pentru un serviciu
Web. Serviciu Web = un serviciu oferit de o aplicatie altor aplicatii, prin intermediul
platformei Web.
• Aplicatiile Web contin componente Web. Acestea sunt caramizile cu care
se poate extinde dinamic functionalitatea unui server Web. In tehnologia
Java, componentele Web sunt miniservere sau pagini JSP.
• Componentele Web sunt gazduite de o platforma speciale de executie
numita container Web. Containerul furnizeaza servicii ca: dispecerizarea
cererilor, securitate, concurenta, gestiunea ciclului de viata, etc.
• O aplicatie Web consta in general din: componente Web, fisiere de
resurse statice si clase/biblioteci de ajutor (engl.helper).
2015
SSI
• SSI (engl.Server Side Include) este o tehnologie ce permite includerea de
informatii intr-o pagina Web inainte de trimiterea paginii la client.
• O pagina care foloseste SSI contine instructiuni speciale. Aceste instructiuni sunt
interpretate de server ori de cate ori pagina este ceruta de un client. Instructiunile
pot specifica: includerea unor documente in pagina curenta (de exemplu un
header sau un footer), a datei curente, a valorii unui contor de acces, etc.
• Avantajul SSI fata de CGI este ca este o tehnologie mult mai simpla si ca nu
implica apelul nici unui program extern.
• Nu exista un standard de SSI si de aceea fiecare server are o sintaxa si
functionalitate proprie pentru SSI. Pentru serverul Apache instructiunile SSI sunt
de forma unor comentarii HTML/XML cu structura urmatoare:
<!-- #comanda atribut1=valoare1 atribut2=valoare2 ... -->
• Un exemplu este urmatorul:
<!--#include virtual="/header.html" -->
• Apache permite folosirea si a unor facilitati SSI avansate desemnate prin
acronimul XSSI. Un exemplu este posibilitatea definirii unui flux de control ca in
programarea procedurala prin comenzile if, elif, else si endif.
2015

Extensia functionalitatii serverelor Web


• Functionalitatea standard oferita de un server Web este insuficienta pentru
programarea aplicatiilor.
• O aplicatie are o arhitectura multi-nivel (engl.n-tier), numarul de niveluri
fiind de obicei minim 3: client, server Web, server de baze de date.
• Pe langa serverul Web mai exista obiectele din domeniul problemei
(engl.business objects). Impreuna ele formeaza nivelul intermediar al unei
arhitecturi tipice pentru o aplicatie de comert electronic.
• O varianta a extinderii functionalitatii unui server Web este folosirea
interfetei CGI, insa ea prezinta dezavantaje:
– Pentru fiecare cerere HTTP trebuie startat un proces separat.
– Interfata dintre serverul Web si scriptul CGI este nesatisfacatoare.
• O abordare eleganta o constituie solutia Java pentru extinderea
functionalitatii unui server Web, si anume miniserverele Java (engl.Java
servlet). Aceasta solutie are urmatoarele avantaje:
– Portabilitate
– Miniserverele sunt rezidente si starea este persistenta intre cereri succesive
– Beneficierea de avantajele tehnologiei Java: orientare pe obiect, modelul de securitate
Java, integrarea relativ usoara cu tehnologii ca RMI si CORBA 2015
CGI
• CGI (engl.Common Gateway Interface) defineste o interfata pentru comunicarea dintre
un server de informatii (cum este cazul unui server Web) si un program de aplicatie.
• CGI este o interfata independenta de limbaj. Este posibil sa se implementeze o aplicatie
CGI (numita si script CGI) in orice limbaj care suporta comunicarea standard intre
procese prin intermediul intrarii si iesirii standard si a variabilelor de mediu. Pentru
scripturile CGI se foloseste deseori unul dintre limbajele: Perl, Python sau Tcl. Se pot
folosi insa si limbaje gen C/C++.
• Procesul de comunicare decurge astfel:
– Dupa primirea cererii HTTP si inaintea pornirii scriptului CGI, serverul initializeaza o
multime de variabile de mediu (engl.environment variables). Aceste variabile vor fi
mostenite de procesul corespunzator lansarii scriptului CGI. Existe variabile independente de
cerere si variabile dependente de cerere. Pe langa aceste variabile de mediu, daca protocolul
este HTTP, se creaza cate o variabila de mediu ce incepe cu prefixul HTTP pentru fiecare
linie din antetul cererii (de exemplu HTTP_ACCEPT).
– Daca cererea contine informatii aditionale dupa antetul cererii, atunci informatia este trimisa
scripului CGI la intrarea standard. Se trimite un numar de octeti egal cu valoarea variabilei de
mediu CONTENT_LENGTH.
– Scriptul genereaza datele de iesire la iesirea standard. Pentru generearea raspunsului catre
client, serverul fie interpreteaza si prelucreaza aceste date, fie le inainteaza nealterate. El
indica acest acest lucru serverului prin antete speciale.

2015

Arhitectura CGI
Server

Client Server HTTP Aplicatie

Date in cererea HTTP


Inainteaza datele aplicatiei

Rezultate pentru server


Returneaza rezultatele clientului

HTTP CGI

2015
Miniservere
• Miniserverele (engl.servlet) sunt programe
asemanatoare cu programele CGI ce ruleaza pe partea
de server in cadrul unui mediu special de executie
(engl. run-time) numit container.
• In principiu un miniserver:
– Preia date de la client
– Genereaza un raspuns, posibil interactionand cu fisiere
si/sau baze de date
– Trimite rezultatul inapoi clientului
• Intr-o arhitectura multi-nivel miniserverele realizeaza
interfata dintre nivelul de prezentare si nivelul de
logica a aplicatiei.
2015

Functionarea miniserverelor
• Presupune urmatorii pasi:
– Un program client emite o cerere HTTP catre un server WWW.
– Serverul interpreteaza cererea si executa o secventa de program careia
ii transmite parametrii cererii.
– Programul apelat interpreteaza parametrii cererii si executa o portiune
de cod care genereaza dinamic o pagina HTML.
• Prelucrarile executate de miniserver pot duce la:
– Generarea unei pagini WWW statice.
– Generarea unei pagini WWW actualizata dinamic.
– Configurarea unei pagini WWW pe baza parametrilor cererii HTTP.
Parametrii sunt preluati de la utilizator printr-un formular HTML.
• In general miniserverele sunt potrivite pentru aplicatiile
orientate pe serviciu sau pentru controlul aplicatiilor orientate
pe prezentare.
2015
Instalarea miniserverelor
• Se instaleaza Tomcat (implementarea de referinta pentru miniservere).
• Se porneste serverul cu comanda startup.
• Se verifica instalarea prin introducerea URL-ului: http://localhost:8080
• Aplicatia Web se instaleaza in directorul webapps al serverului. Pentru
fiecare aplicatie exista cate un subdirector. Se poate folosi ca exemplu
aplicatia ROOT.
• Se creaza directorul noi aplicatii, fie el mywebapp.
• Acest director va contine un subdirector WEB-INF/classes unde se vor
instala clasele miniserverelor.
• In radacina directorului WEB-INF se creaza descriptorul de instalare a
aplicatiei (engl.deployment descriptor). Acesta este un fisier cu numele
web.xml. El va defini miniserverele din cadrul aplicatiei.
• Se creaza un fisier HTML index.html care permite invocarea
miniserverului. Acest fisier se poate plasa in radacina aplicatiei. El poate fi
afisat in programul navigator folosind URL-ul:
http://localhost:8080/mywebapp/index.html 2015

Descriptorul de instalare
• Miniserverul se descrie cu marcajele servlet si servlet-mapping.

<?xml version="1.0" encoding="ISO-8859-1" ?>


<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet>
<servlet-name>FirstServlet</servlet-name>
<servlet-class>FirstServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FirstServlet</servlet-name>
<url-pattern>/FirstServlet</url-pattern>
</servlet-mapping>
</web-app>
2015
Fisierul HTML de invocare
• Fisier HTML pentru invocarea miniserverului cu un buton de activare:
<HTML>
<HEAD>
<TITLE>A First Servlet</TITLE>
</HEAD>
<BODY>
<BR><BR><BR>
<CENTER>
<FORM METHOD=GET ACTION="FirstServlet">
<INPUT TYPE="Submit" VALUE = "Click me!">
</FORM>
</CENTER>
</BODY>
</HTML>
• Miniserverul se poate invoca direct cu urmatorul URL:
http://localhost:8080/<WebAppName>/<ServletName>
http://localhost:8080/mywebapp/FirstServlet
2015

Interfata implementata de un miniserver


• La fel ca si o miniaplicatie, un miniserver nu contine o functie main(). El va fi
invocat de catre containerul de miniserveri la receptionarea unei cereri HTTP de
catre serverul WWW. Pentru aceasta un miniserver trebuie sa implementeze o
interfata javax.servlet.HttpServlet
• Dezvoltarea unui minserver presupune extinderea clasei
javax.servlet.HttpServlet si redefinerea metodelor sale. Interfata
cuprinde metodele service(), init() si destroy().
• La executarea unei cereri catre un miniserver au loc urmatoarele: i) daca
miniserverul nu exista atunci containerul de miniserveri incarca clasa
corespunzatoare miniserverului, creaza o instanta a acestei clase si apeleaza
metoda init(); ii) se apeleaza metoda service(). In functie de tipul
cererii, ea va apela o metoda doYYY() unde YYY identifica cererea HTTP, de
exemplu doGet() sau doPost().
• Cand containerul trebuie sa descarce miniserverul din memorie el va apela
metoda destroy().
• Metodele init() si destroy() se refera la ciclul de viata al miniserverului
(la fel ca la miniaplicatii). Aceste operatii se executa mult mai rar decat
service().
2015
Prelucrarile din cadrul unui miniserver
• In cadrul metodelor init() si destroy() se implementeaza acele prelucrari care
asigura persistenta informatiei stocate de miniserver.
• In metodele service() sau doYYY() se implementeaza prelucrarile legate de tratarea
cererilor primite de la client. Acestea presupun de obicei urmatoarele:
– Setarea tipului continutului in obiectul raspuns HTTP, de tip
javax.servlet.http.HttpServletResponse:
raspuns.setContentType("text/html");
– Obtinerea unui flux de iesire la nivel de octet (OutputStream obtinut din raspuns
cu getOutputStream()) sau la nivel de caracter (PrintWriter obtinut din
raspuns cu getWriter()):
PrintWriter iesire = raspuns.getWriter();
– Obtinerea valorilor parametrilor cererii setati de client in formularul HTML, din
obiectul cerere de tip javax.servlet.http.HttpServletRequest, cu
getParameter(). Daca numele parametrilor este necunoscut atunci se poate
obtine lista numelor parametrilor cu getParameterNames().
– Construirea raspunsului prin scrierea in fluxul de iesire a unor enunturi HTML.
• Pentru aflarea de informatii de configurare se foloseste metoda
getServletConfig() care intoarce un obiect SevletConfig. Din el se pot
extrage parametrii de initializare ai miniserverului cu getInitParameter() si
getInitParameterNames().
2015

Exemplu de miniserver
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class FirstServlet extends HttpServlet {
public void doGet(HttpServletRequest
request,HttpServletResponse response)
throws IOException,ServletException {
response.setContentType("text/HTML");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>Simple Servlet</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("<BR><BR><BR>");
out.println("<CENTER><H1>A Simple Servlet</H1></CENTER>");
out.println("</BODY>");
out.println("</HTML>");
out.flush();
}
}
2015
Invocare miniserver cu parametrii
<FORM METHOD=GET ACTION="PersonalServlet">
Enter your first name:
<INPUT TYPE="Text" NAME="FirstName" VALUE="">
<BR><BR>
<INPUT TYPE="Submit" VALUE="Submit">
</FORM>
• Se poate invoca si direct cu URL-ul:
http://localhost:8080/mywebapp/PersonalServlet?FirstName=<v
aloare>
• Preluarea parametrilor se face cu metodele clasei HttpServletRequest:
String getParameter(String <name>) – Determina valoarea unui parametru
trimis prin GET si POST
Enumeration getParameterNames() – Returneaza numele tuturor
parametrilor trimisi prin POST
String[] getParameterValues(String <name>) – Returneaza valorile
unui parametru care poate avea mai mult de o valoare.

2015

Cod miniserver cu parametrii


import javax.servlet.http.*;
public class PersonalServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException,ServletException {
response.setContentType("text/HTML");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>Simple Servlet</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("<BR><BR><BR>");
String name = request.getParameter("FirstName");
out.println("<CENTER><H1> A Simple Servlet for ");
out.println(name + "</H1></CENTER>");
out.println("</BODY>");
out.println("</HTML>");
out.flush();
}
}
2015
Obiecte partajate
• Componentele Web in general si miniserverele in particular folosesc
de obicei si alte obiecte pentru a-si indeplini sarcinile. Astfel: i) pot
folosi obiecte private; ii) pot folosi obiecte publice – atribute ale
unui domeniu standard; iii) pot accesa baze de date; iv) pot accesa
alte resurse Web.
• Componentele Web cooperante pot partaja informatii sub forma
unor obiecte definite ca atribute ale unui domeniu standard: context
Web (aplicatie), sesiune, cerere HTTP si respectiv pagina JSP.
• Pentru reprezentarea acestor patru domenii, in pachetul
javax.servlet sunt definite patru clase: ServletContext,
HttpSession, ServletRequest si JspContext.
• Accesul la aceste obiecte se face prin metode de tip
[get|set]Attribute.

2015

Sesiuni
• HTTP este un protocol fara stare (engl. stateless). Acest lucru
inseamna ca orice pereche cerere-rapsuns reprezinta o
tranzactie (conversatie) separata.
• Uneori este insa nevoie ca datele achizionate sa se pastreze
intre interactiuni. Un exemplu: un cos electronic de cumparaturi
trebuie actualizat astfel incat sa reflecte multiumea tuturor
optiunilor de cumparare ale utilizatorului.
• Din acest motiv miniserverele implementeaza conceptul de
sesiune ce reprezinta un container pentru datele privind
activitatile unui client sunt stocate si eventual accesate de toate
miniserverele care au acces la obiectul respectiv.
• O sesiune expira automat dupa o perioada de timp prestabilita
(implicit 30 s) sau daca este invalidata explicit de miniserver
(metoda invalidate()).
2015
Accesul la un obiect sesiune
• Crearea unei sesiuni (varianta fara parametrii sau cea cu parametrul create
= true fie intoarce sesiunea curenta, daca exista, fie creaza o sesiune noua
si o returneaza):
HttpSession getSession()
HttpSession getSession(boolean create)
• Un obiect sesiune contine o multime de perechi atribut-valoare. Fiecare
nume este String si fiecare valoare este Object. Valorile trebuie sa fie
obiecte serializabile.
• Adaugarea de informatie la sesiune se face prin:
void setAttribute(String <name>, Object <value>)
• Eliminarea unui valori se face cu metoda:
Object removeAttribute(String <name>)
• Regasirea unei valori se face cu metoda:
Object getAttribute(String <name>)
• Determinarea tuturor numelor se face cu:
String[] getAttributeNames()
2015

Cookies
• Cookies ofera o alta modalitate de a pastra datele utilizatorului
in timpul cat acesta foloseste o aplicatie Web.
• Sesiunile pastreaza datele doar pe durata unei vizite a aplicatiei.
cookies pastreaza datele si intre vizite succesive. Sesiunile se
bazeaza tot pe cookies.
• Un cookie este o pereche nume-valoare care asociaza o valoare
cu un atribut. Este posibil sa se pastreze o sesiune pentru durata
unei sesiuni, ea putand fi pastrata pe calculatorul clientului
pentru utilizari viitoare.
• O cookie se pastreaza intr-un fisier trimis de server clientului.
Fisierul este retransmis catre server la fiecare vizita ulterioara a
acestuia a aplicatiei de pe server.
2015
Folosirea cookies
• O cookies se reprezinta cu clasa Cookie.
• Constructorul este:
Cookie(String <name>, String <value>)
• Adaugarea unui cookie la un obiect HttpServletResponse:
void addCookie(Cookie <cookie>)
• Determinarea cookie-urilor dintr-o cerere HttpServletRequest:
Cookie[] getCookies()
• Alte metode utile ale clasei Cookie:
void setComment(String <value>)
String getComment()
String getName()
String getValue()
void setValue(String <value>)
int getMaxAge() 2015

Fire multiple in miniservere


• Containerul de miniserveri utilizeaza fire de executie separate pentru tratarea
cererilor. Pentru aceasta containerul are o rezerva (engl.pool) de fire de executie.
Fiecarei cereri i se aloca un fir.
• Deoarece este teoretic posibil sa se execute cereri simultane pentru un acelasi
miniserver, se pune problema gestionarii corecte a resurselor miniserverului ce
sunt partajate de aceste cereri multiple. Resursele partajate pot fi: atribute ale
domeniilor standard, variabile membre ale clasei miniserverului, fisiere, baze de
date, conexiuni de retea, etc.
• Din acest motiv controlul accesului la resursele partajate se va realiza folosind
tehnici de sincronizare.
• Variante:
– Cea mai simpla solutie este ca metoda service() sa se implementeze cu
synchornized.
– Daca insa sectiunea critica din cadrul acestei functii se executa conditionat, atunci
este mai eficient sa se foloseasca synchronized doar pentru portiunea de cod
corespunzatoare acelei sectiuni critice.
– Se poate crea o clasa pentru accesul la resursa partajata, metodele de acces fiind
declarate synchronized.
2015
JSP
• JSP (engl.JavaServer Pages) este o tehnologie pentru
generarea de pagini dinamice bazata pe ideea mixarii de cod
Java cu cod HTML in paginile Web. Este recomandata pentru
aplicatiile Web orientate pe prezentare.
• JSP functioneaza peste o arhitectura de miniservere.
• Arhitectura JSP poate fi descrisa ca o abstractizare de nivel
inalt a miniserverelor Java.
• La incarcarea unui JSP, se genereaza automat codul java
pentru miniserverul corespunzator si apoi acesta este compilat
si incarcat in containerul de miniserveri. Acest proces se
repeta ori de cate ori codul JSP este modificat.
• JSP Standard Tag Library (JSTL) este o colectie de biblioteci
de tag-uri ce implementeaza functionalitati de baza necesare
aplicatiilor Web.
2015

PHP
• Este o tehnologie bazata pe un limbaj de scripting pe partea de
server, inspirat din C si Perl.
• Ofera un acces facil la o varietate de baze de date bazate pe
SQL: mySQL, Oracle, PostgresSQL, ODBC, dBASE,
Informix, etc si se poate folosi impreuna cu o varietate de
servere Web incluzand Apache si MS IIS.
• Limbajul PHP a fost creat in 1995 de Rasmus Lerdorf (danez
cu cetatenie canadiana).
• http://en.wikipedia.org/wiki/PHP
• Versiunea curenta este PHP 5.4
• http://www.php.net/

2015
ASP
• ASP (Active Server Pages) este o tehnologie a firmei Microsoft pentru
realizarea paginilor de WWW dinamice si interactive, aparuta in 1996.
• ASP se bazeaza pe o interfata de programare oferita de un server Web,
numita si ISAPI – Internet Server Application Programming Interface.
• ASP se bazeaza pe limbaje de scripting (la fel ca JSP si PHP) si pe un
motor de scripting. Un astfel de motor este inclus in MS IIS.
• Interpretoarele incorporate in motorul ASP se bazeaza pe tehnologia
COM. Motorul curent suporta limbajele de scripting JScript (versiunea
JavaScript promovata de Microsoft) si VBScript.
• Noua generatie ASP este denumita ASP+ si ruleaza sub platforma
Windows .NET. Ea suporta nativ si limbajul C#. Spre deosebire de ASP,
scripturile ASP+ sunt compilate, fapt ce contribuie la cresterea vitezei de
prelucrare.

2015

Serverul de aplicatii ZOPE


• ZOPE – Z Object Publishing Environment este un server de
aplicatii Web disponibil liber si dezvoltat pornind de la ideea
abstractizarii interfetei dintre serverul Web si cel de aplicatie.
• ZOPE (www.zope.org) ofera:
– Un server Web
– Un model obiectual de dezvoltare a aplicatiilor bazat pe limbajul
Python incluzand: tipare pentru generarea de pagini dinamice, un
limbaj de scripting propriu – DTML, un model obiectual al datelor.
– O multime de componente dezvoltate de comunitatea utilizatorilor
ZOPE si disponibile liber.
• Folosind ZOPE se pot dezvolta aplicatii puternice si complete,
ignorand complet asa-numitele tehnologii “la moda”: Java,
ASP sau PHP.
2015
SD bazate pe middleware agent
(componente)

Capitolul 8

2015

Programare orientata pe agenti


• Programarea orientata pe agenti – POA este o paradigma
software relativ noua care reuneste idei din domeniile
sistemelor distribuite (mai precis middleware), programare
orientata pe obiect si inteligenta artificiala. POA modeleaza o
aplicatie software sub forma unei colectii de componente
software numite agenti.
• Modelul arhitectural al unei aplicatii dezvoltata folosind POA
este in esenta P2P in sensul ca fiecare agent este capabil sa
initieze o comunicare cu orice alt agent si respectiv sa fie
subiectul implicarii intr-o comunicare initiata de un alt agent.
• Dpdv al SD, POA presupune folosirea unui middlleware
orientat pe agenti care in esenta ofera suportul pentru
asigurarea independentei de platforma si domeniu, si respectiv
a interoperabilitatii necesare dezvoltarii facile a unei aplicatii
distribuite.
2015
Ce este un agent software ?

• Definitie: Agent = un sistem (componenta) de calcul


situat(a) intr-un mediu si care este capabil(a) de
actiuni autonome in acest mediu in scopul atingerii
obiectivelor pentru care el (ea) a fost proiectat(a).

• Termenul de agent este supraincarcat. De aceea se


foloseste deseori agent software.

2015

Caracteristicile unui agent software ?


• Autonomie = capacitatea de a realiza independent sarcini complexe,
deseori de durata
• Reactivitate = capacitatea de a percepe mediul si de a raspunde la
schimbarile din mediu
• Proactivitate = capacitatea de a prelua initiativa in realizarea unei
anumite sarcini fara un stimul explicit din exterior, evenual din partea
unui utilizator – goal directed behavior
• Interactivitate = capacitatea de a comunica/interactiona cu alte entitati in
sensul (i) folosirii capabilitatilor acestora rspectiv (ii) sprijinirii acestora
in realizarea propriilor sau altor obiective
• Mobilitate = capacitatea unui agent de a migra intr-o retea de
calculatoare
• Sociabilitate = capacitatea de a coppera cu alti agenti pentru realizarea
de sarcini complexe
• Alte caracteristici: adaptivitate/invatare, benevolenta, incredere,
rationalitate
2015
Agenti sau actori ?
• Definitie: Actor = entitate de “categorie usoara” (engl. leightweight) pentru calcul
concurent, asincron si reactiv.
• Modelul actor a fost introdus de Carl Hewitt in 1973.
• Un actor faciliteaza implementarea sistemelor de calcul concurente si distribuite bazate
pe comunicatie asincrona prin schimb de mesaje.
• In esenta un actor are urmatoarele caracteristici:
– Comunica asincron cu alti actori prin schimb de mesaje
– Este reactiv – poate reactiona la primirea de mesaje, prin filtrare folosind identificare de
sabloane (engl. pattern matching)
– Implementeaza transparenta locatiei – adica este nativ distribuibil. Aplicatia se poate proiecta
fara a prestabili modul de distribuire si instalare a actorilor.
– Grupurile de actori sunt structurate arborescent, astfel incat un actor parinte este responsabil
de coopii sai – similar oarecum cu procesele din sistemele de operare.
– Pot oferi proprietati tranzactionale, de exemplu atomicitate.
• Exemplu: platforma AKKA: http://akka.io/
• Permite dezvoltarea actorilor folosind limbajele Java si Scala.
• Scala: http://www.scala-lang.org/ este un limbaj de programare modern, multi-
paradigma, ce integreaza: programare orientata pe obiect, programare functionala.
Permite cresterea productivitatii programarii Java.
2015

Standardele FIPA
• Foundation for Intelligent Physical Agents
(http://www.fipa.org/) – FIPA este o asociatie
internationala non-profit care se ocupa cu
dezvoltarea unei colectii de standarde legate de
tehnologia agentilor software.

• Scopul declarat al FIPA este: “FIPA is an


IEEE Computer Society standards
organization that promotes agent-based
technology and the interoperability of its
standards with other technologies. [...] FIPA
specifications represent a collection of
standards which are intended to promote the
interoperation of heterogeneous agents and the
services that they can represent.”
2015
Concepte FIPA
• Conceptele de baza ale FIPA se refera la:
– Comunicarea intre agenti
– Managementul agentilor
• Comunicarea intre agenti se realizeaza exclusiv prin
mesaje. FIPA defineste 22 de tipuri de mesaje numite si
acte comunicative. Aceste tipuri mesaje au fost inspirate
din teoria actelor de vorbire – speech act theory
dezvoltata de John Searl. Un mesaj se reprezinta folosind
limbajul FIPA-ACL – Agent Communication Language.
• Managementul agentilor presupune standardizarea unei
infrastructuri minimale necesara pentru existenta,
operarea si gestiunea agenilor.
2015

Managementul agentilor (I)

2015
Managementul agentilor (II)
• Agent Platform – AP. Reprezinta infrastructura in care agentii
exista. AP poate fi distribuita pe mai multe calculatoare. FIPA
nu precizeaza detaliile de implementare ale AP.
• Agent. Reprezinta un proces gazduit de o AP ce ofera unul sau
mai multe servicii ce pot fi publicate prin intermediul unei
descrieri de serviciu – Agent Service Description. Un agent are
un identificator unic numit AID. FIPA nu precizeaza maniera
de proiectare a serviciilor (numite si capabilitati) ale unui
agent. Singura cerinta este respectarea structurii si codificarii
mesajelor transmise catre alti agenti.
• Message Transport Service – MTS. Reprezinta acel serviciu al
unei AP pentru transportul mesajelor intre agentii unei AP sau
din AP-uri diferite. MTS foloseste un Message Transport
Protocol – MTP. MTS este furnizat de catre un Agent
Communication Channel – ACC ce raspunde de transmiterea
mesajelor folosind MTP.
2015

Managementul agentilor (III)


• Agent Management System – AMS.
– Componenta obligatorie a unei AP responsabila cu gestionarea tuturor operatiilor
necesare functionarii unei AP: crearea/distrugerea agentilor, migrarea agentilor in
cadrul AP sau in afara AP.
– Orice agent se va inregistra la AMS pentru a obtine un AID fiind astfel retinut in
cadrul AMS impreuna cu starea sa curenta: activ, suspendat, sau in asteptare.
– AMS functioneaza ca serviciu de pagini albe – white pages, numit si serviciu de
nume – name service in SD. Viata unui agent intr-o AP dureaza pana cand
inregistrarea agentului in AMS este stearsa. Un agent poate fi cautat prin intermediul
AMS pe baza descrierii sale.
• Directory Facilitator – DF.
– Componenta optionala a unei AP ce furnizeaza un serviciu de tip pagini aurii –
yellow pages pentru alti agenti. In SD acest serviciu se numeste si serviciu de
director – directory service.
– O AP poate contine un numar arbitra de DF-uri interconectate intr-o federatie.
– Un agent ce doreste sa-si publice serviciile pentru alti agenti va trebui sa gaseasca un
DF si sa-si inregistreze (register) descrierea la acesta. Ulterior el poate cere DF-ului
sa stearga (deregister) sau sa modifice (modify) aceasta inregistrare. Un agent poate
cere cautarea (search) unui serviciu in DF ce sa corespunda descrierii furnizate in
cererea de cautare. 2015
Comunicarea intre agenti (I)
• Stiva de protocoale FIPA poate fi descompusa pe urmatorele nivele:
– Nivelul 1 – Transport. El defineste protocolul de nivel cel mai coborat pe care se
bazeaza transportul mesajelor intre agenti. FIPA a definit urmatoarele protocoale de
transport a mesajelor – message transport protocols sau MTP: IIOP (protocolul de
transport definit de standardul CORBA), WAP (protocolul de comunicatie wireless)
si HTTP.
– Nivelul 2 – Codificare. FIPA a definit cateva reprezentari ale mesajelor pentru a
permit o structurare de nivel inalt: XML, String si BitEfficient (pentru conexiuni de
viteza scazuta).
– Nivelul 3 – Mesagerie: Structura unui mesaj este definita independent de modul
particular de codificare a mesajelor pentru a permite o flexibilitate sporita. La acest
nivel se definesc parametrii cheie necesari pentru realizarea unei interactiouni, pe
langa continutul propriuzis al mesajului: expeditorul si receptorul, tipul mesajului
(actul comunicativ), valorile timeout pentru primirea raspunsurilor.
– Nivelul 4 – Ontologie: Termenii individuali ce pot apare in continutul unui mesaj pot
fi raportati la un model conceptual (sau ontologie) specifica aplicatiei. In acest fel
FIPA permite utilizarea ontologiilor pentru exprimarea continutului unui mesaj, insa
nu specifica nici o ontologie specifica domeniului si nici o reprezentare particulara a
unei astfel de ontologii. Este astfel posibila folosirea unor ontologii definite in Web.
2015

Comunicarea intre agenti (II)


• Stiva de protocoale FIPA se descompune pe urmatorele nivele:
– Nivelul 5 – Continut: Pentru exprimarea continutului se poate folosi
orice limbaj de reprezentarea. Cu toate acestea FIPA a definit niste
indicatii de folosire a formulelor logice generale cu predicate si a unor
operatii algebrice pentru combinarea si selectarea conceptelor. Cel mai
raspandit limbaj este FIPA-SL ce imbina formulele logice (not, or,
implies, equiv, etc.) cu operatiile algebrice (any si all).
– Nivelul 6 – Act comunicativ: Reprezinta a clasificare simpla a mesajelor
in functie de actiunea (numita si performative) pe care o implica: inform,
request, propose, cfp, agree, etc.
– Nivelul 7 – Protocol de interactiune: Mesajele nu sunt interschimbate
izolat, ci schimburile de mesaje fac parte deobicei dintr-o secventa de
interactiune numita si conversatie. FIPA a definit cateva protocoale de
interactiune care stabilesc schimburi tipice de mesaje cum este spre
exemplu protocolul request-reply.
2015
Structura unui mesaj FIPA

(request
:sender (agent-identifier :name alice@mydomain.com)
:receiver (agent-identifier :name bob@yourdomain.com)
:ontology travel-assistant
:language FIPA-SL
:protocol fipa-request
:content
"((action
(agent-identifier :name bob@yourdomain.com)
(book-hotel :arrival 15/10/2006 :departure 05/07/2002 ... )
))"
) 2015

Introducere in JADE
• JADE este o platforma software complet compatibila cu specificatiile FIPA
ce furnizeaza functionalitati middleware de baza, independente de aplicatie
si simplifica dezvoltarea aplicatiilor distribuite folosind POA.

2015
Arhitectura JADE (I)
• O platforma JADE este compusa din containere distribuite intr-o retea de
calculatoare.
• Un container este reprezentat de un process Java ce contine runtime-ul
JADE si serviciile necesare pentru gazduirea si executarea agentilor.
• Exista un container special numit Main-container ce reprezinta punctul de
start – bootstrap al platformei. El este primul container care se lanseaza la
pornirea platformei. Toate celelalte containere ale platformei se
inregistreaza la pornire la Main-container. Numele lor implicite sunt
Container-1, Container-2, ..., dar pot fi redefinite de la linia de comanda.
• Main-container are urmatoarele responsabilitati:
– Gestiunea tabelei de containere – CT ce este un registru cu referintele si adresele de
transport corespunzatoare toate containerelor din platforma
– Gestiunea tabelei globale cu descrierile agentilor din platforma – GADT impreuna cu
starea si locatia lor curente
– Gazduirea AMS si a DF, cei doi agenti speciali ce reprezinta serviciul de pagini albe
pentru gestiunea agentilor din platforma si respectiv serviciul implicit de pagini aurii.
• Fiecare container mentine o tabela cu descrierile agentilor locali – LADT.
2015

Arhitectura JADE (II)


• Fiecare container detine un cache local cu o copie a GADT
gestionata local. Astfel, operatiile de interactiune din cadrul
platformei nu implica in general pe Main-container, ci doar
cache-urile locale impreuna cu cele doua containere ce
gazduiesc agentii care fac obiectul operatiei respective
(expeditorul si receptorul mesajului).
• Cand un container trebuie sa descopere unde se gaseste
recipientul unui mesaj si operatia de cautare in LADT esueaza
el va contacta Main-container pentru a obtine referinta
corespunzatoare iar aceasta referinta va fi totodata stocata in
cache-ul local. In cazul in care agentul respectiv a migrat se
obtine o exceptie care va declansa automata reimprospatarea
cache-ului local.

2015
Arhitectura JADE (III)
• In acest fel Main-container nu este un punct de congestie a
performantelor sistemelui – system bottleneck. Cu toate acestea
el este un punct critic in functionarea sistemului – single point
of failure.Pentru a preveni acest dezavantaj JADE dispune de
un serviciu special de replicare – Main Replication Service.
• Identitatea unui agent este continuta in Agent Identifier – AID
ce este compus dintr-o multime de atribute conforme cu
semantica specificata de FIPA. Elementele de baza ale unui
AID sunt:
– numele agentului = un identificaor unic al agentului construit de JADE
prin concatenarea numelui local (suficient pentru unicitatea intr-o
platforma) si numele platformei.
– adresele agentului = adresele de transport ale platformei. O astfel de
adresa reprezinta o adresa de tranport corespunzatoare unui MTP unde
se pot transmite mesaje FIPA.
2015

Arhitectura JADE (IV)

2015
Rularea platformei
• Se descarca kit-ul JADE de la http://jade.tilab.com/.
• Se dezarhiveaza arhivele intr-un director care va reprezenta radacina
sistemului JADE.
• Se creaza un subdirector bin in radacina JADE sau unde se vor depune
fisierele de comenzi – bat pentru rularea JADE.
• Se creaza o comanda pentru setarea CLASSPATH catre bibiotecile JADE:
set JADE_HOME=C:\software\jade
set CLASSPATH=%JADE_HOME%\lib\jade.jar; %JADE_HOME%
\lib\jadeTools.jar; %JADE_HOME%\lib\http.jar; %JADE_HOME%
\lib\iiop.jar; %JADE_HOME% \lib\commons-codec\commons-codec-
1.3.jar;%JADE_HOME%\classes
• Se porneste platforma (cu conditia ca java sa se gaseasca in PATH).
Optiunea –gui are ca efect lansarea Remote Monitoring Agent – RMA, un
agent special cu interfata grafica pentru monitorizarea platformei.
java jade.Boot –gui
• Crearea unui nou container se poate face cu una din comenzile:
java jade.Boot -host NumeHost –container
java jade.Boot -host NumeHost -container -container-name
NumeContainer
2015

JADE MTS
• Pentru interoperabilitate intre platforme non-JADE dar conforme FIPA JADE
implementeaza toate MTP-urile standard impuse de FIPA. Un MTP implica
definitia protocoului de transport corespunzator impreuna cu codificarea stanrd a
plicului pentru un mesaj ce contine informatia de transport a mesajului.
• Astfel unul dintre mesajele de lansare ale platformei este:
INFO: MTP addresses:
http://Toshiba:7778/acc
• Acest lucru arata ca pentru Main-container JADE porneste implicit cu un MTP
bazat pe HTTP. Pentru celelalte containere ale platformei nu se activeaza nici un
MTP.
• La primirea unui mesaj din afara platformei, MTP-ul pentru Main-container
dirijeaza corect mesajul in interiorul platformei. Intern platforma foloseste un
protocol proprietar de transport numit Internal Message Transport Protocol –
IMTP.
• Se pot activa insa explicit MTP-uri pentru orice alt container al platformei. In
acest fel platfoma va primi noi adrese de transport.
• Daca nu este nevoie de interoperabilitate FIPA in afara platformei, optiunea
–nomtp va conduce la inhibarea crearii implicite a HTTP MTP pentru Main-
container.
2015
JADE IMTP
• IMTP este folosit pentru schimbul de mesaje intre agentii aflati in
containere diferite, doar in cadrul unei aceleasi platforme JADE.
• Nu e nevoie ca IMTP sa fie compatibil cu propunerile de MTP din
standardul FIPA si este considerabil diferit de MTP-urile destinate
interoperabilitatii intre platforme.
• IMTP permite unui container nou sa se conecteze pe un port la Main-
container.
• IMTP este bazat pe un protocol proprietar ce foloseste socluri TCP.
• Optiunile:
– -host hostName
– -port portNumber
• sunt destinate configurarii IMTP.
• La pornire JADE afiseaza:
– Gazda si portul unde a fost pornit Main-container: jicp://10.8.0.14:2000
– Numele lui Main-container: Agent container Main-Container@10.8.0.14 is ready.

2015

Exemplu de agent JADE


import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
public class HelloWorldAgent extends Agent {
public void setup() {
System.out.println("Hello. My name is "+getLocalName());
addBehaviour(new CyclicBehaviour() {
public void action() {
ACLMessage msgRx = receive();
if (msgRx != null) {
System.out.println(msgRx);
ACLMessage msgTx = msgRx.createReply();
msgTx.setContent("Hello!");
send(msgTx);
}
else {
block();
}
}
});
}
} 2015
Administrarea platformei
• Consola de administrare
– Remote Monitoring Agent – RMA este o consola grafica pentru managementul
platformei. Ea permite crearea si controlul agentilor, inspectarea containerelor,
controlul unei platforme la distanta – remote platform, etc
• DummyAgent
– Se foloseste pentru a trimite si a receptiona stimuli de la alti agenti in scopul testarii
acestora, in timpul dezvoltarii unei aplicatii
• Agentul Sniffer
– Se foloseste pentru a depana interactiunile dintre agenti
– Permite urmarirea anumitor agenti in scopul inregistrarii mesajelor transmise si
primite de acestia. Mesajele iregistrate pot fi inspectate, salvate si reincarcate dintr-
un fisier
• Agentul Introspector
– Se foloseste pentru a depana comportamentul unui agent.
– Permite monitorizarea si controlul ciclului de viata al unui agent, inspectarea cozilor
de mesaje de intrare si iesire.
– Se permite si executarea pas cu pas a comportamentului unui agent. Un singur pas nu
este insa o instructiune Java, ci executarea unui apel al metodei action9) din
comportamentul unui agent.
2015

Elemente de baza ale programarii JADE


• Crearea agentilor
– Ciclul de viata al unui agent JADE: crearea si terminarea
• Definirea sarcinilor agentilor:
– Modelul de executie a sarcinilor
– Definirea si asignarea sarcinilor
• Interactiunea dintre agenti:
– Crearea mesajelor
– Trimiterea si receptionarea mesajelor
• Publicarea si descoperirea serviciilor in cataloagele
pagini aurii

2015
Crearea unui agent (I)
• Presupune crearea unei clase ce mosteneste jade.core.Agent.
• Initializarea unui agent se face prin redefinirea metodei setup(). Deobicei
initializarea presupune:
– Crearea si afisarea unui GUI
– Crearea unei conexiuni la o baza de date
– Inregistrarea unor servicii in catalogul pagini aurii
– Crearea si adaugarea unor comportamente initiale unui agent – clase ce descriu
sarcinile agentului si modul lor de realizare
• Identificarea unui agent se face consistent cu specificatiile FIPA:
– Identificarea unui agent se face printr-o instanta a clasei jade.core.AID.
– Un AID contine un GUID – Global Unique Name si un numar de adrese.
– Un GUID in JADE este format din: (i) un nume local si (ii) numele platformei.
Numele local trebuie sa fie unic in cadrul platformei. Platforma este responsabila cu
verificarea/asigurarea unicitatii sale.
• Spre exemplu:
– Nume local: Guru
– GUID: Guru@Toshiba:1099/JADE
– O adresa (pot fi mai multe, cate una pentru fiecare MTP instalat:
http://Toshiba:7778/acc.
2015

Crearea unui agent (II)


import jade.core.Agent;
import java.util.Iterator;
public class SimpleAgent extends Agent {
protected void setup() {
// Printout a welcome message
System.out.println("Hello World. I’m an agent!");
System.out.println(
"My local-name is "+getAID().getLocalName());
System.out.println("My GUID is "+getAID().getName());
System.out.println("My addresses are:");
Iterator it = getAID().getAllAddresses();
while (it.hasNext()) {
System.out.println("- "+it.next());
}
}
}

2015
Crearea unui agent (III)
• Dupa compilare, clasa SimpleAgent se poate folosi pentru crearea de
agenti.
• O varianta este ca un agent sa se creeze de la linia de comanda, fie la
crearea Main-container, fie la crearea unui alt container, in felul urmator:
java jade.Boot -gui NumeAgent:ClasaAgent
java jade.Boot -host NumeCalculator -container NumeAgent:ClasaAgent
• O alta posibiltte este crearea unui agent prin incarcarea clasei
corespunzatoare din consola GUI a RMA. Pentru aceasta se face click-
dreapta pe containerul in care se doreste crearea agentului, se alege
optiunea Start New Agent si se introduc numele agentului si numele
clasei. Calea catre clasa trebuie sa se gaseasca in CLASSPATH-ul folosit
la lansarea containerului respectiv.
• Atragem atentia ca daca la pornire nu se indica explicit numele platformei
cu optiunea:
–name NumePlatforma
aceasta va primi un nume implicit ce contine numele calculatorului gazda
pe care a fost pornita si portul respectiv.
2015

Terminarea unui agent


• Un agent de tip SimpleAgent afiseaza un mesaj si apoi ramane activ. Pentru terminare, un
agent va invoca metoda doDelete(). Invocarea sa va conduce la apelul metodei
takeDown(), exact inaintea terminarii agentului. Aici se realizeaza deobicei dezalocarea
resurselor alocate agentului. In exemplul de mai jos un agent este creat, apoi terminat, iar
inainte de terminare afiseaza un mesaj.
import jade.core.Agent;
public class TerminateAgent extends Agent {
protected void setup() {
// Printout a welcome message
System.out.println("Hello World. I am an agent!");
System.out.println(
"My local-name is "+getAID().getLocalName());
System.out.println("My GUID is "+getAID().getName());
doDelete();
}

protected void takeDown() {


System.out.println("Bye World. I am going off-line ...");
}
} 2015
Transmiterea de parametrii unui agent
• La pornire un agent poate primi un vector de argumente sub forma unui vector de Object.
Dupa pornire, agentul poate obtine argumentele cu metoda:
Object[] getArguments();
• Lansarea unui agent cu argumente se face cu comanda:
java jade.Boot -host NumeCalculator -container NumeAgent:ClasaAgent(arg1 arg2 arg3 ...)
import jade.core.Agent;
public class AgentWithArgs extends Agent {
protected void setup() {
// Printout a welcome message
System.out.println("Hello World. I am an agent!");
System.out.println("My local-name is "+getAID().getLocalName());
System.out.println("My GUID is "+getAID().getName());
System.out.println("My arguments are:");
Object[] args = getArguments();
if (args != null) {
for (int i = 0; i < args.length; ++i) {
System.out.println("- "+args[i]);
}
}
}
}
2015

Comportamentul agentilor
• Sarcinile pe care trebuie sa le realizeze un agent se definesc prin multimea
de comportamente (engl. behaviour) ale agentului respectiv.
• Un comportament este o instanta a clasei abstracte
jade.core.behaviours.Behaviour.
• Un comportament se poate adauga la un agent cu ajutorul urmatoarei
metode a clasei jade.core.Agent:
public void addBehaviour(Behaviour b);
• Crearea si adaugarea comportamentelor unui agent se face deobicei la
initializarea agentului, in corpul metodei setup().
• Clasa jade.core.behaviours.Behaviour contine doua metode abstracte:
public abstract void action();
public abstract boolean done();
• Metoda action() defineste operatiile pe care trebuie sa le realizeze agentul
in cursul realizarii comportamentului respectiv.
• Metoda done() indica daca executia comportamentului respectiv – a
terminat (action() intoarce true) sau nu (action() intoarce false).
2015
Planificarea comportamentelor
• Un agent poate executa comportamentele asignate in mod concurent.
• Planificarea comportamentelor nu este preemptiva ci este cooperativa.
Cand un comportament este planificat pentru executie, se apeleaza metoda
sa action() si executia se termina doar la terminarea acestei metode.
Programatorul va decide cand un agent va comuta executia de la un
comportament la alt comportament.
• Acest model poate parea dificil, necesita un efort suplimentar de
programare, dar are urmatoarele avantaje:
– Se foloseste un singur fir de executie pentru fiecare agent. Acest lucru este important
mai ales in mediile in care resursele sunt limitate, de exemplu telefoanele celulare
– Performantele sunt mai bune deoarece comutarea comportamentelor este astfel mult
mai rapida decat comutarea firelor Java
– Elimina sincronizarile necesare pentru accesul concurent al comportamentelor unui
agent la resursele comune ale agentului
– La comutarea unui comportament starea unui agent nu include informatii legate de
stiva. Acest lucru permite: (i) salvarea persistenta a starii unui agent astfel incat
executia sa fie reluata ulterior (agent persistency), (ii) transferarea agentului pentru
executie intr-un alt container (agent mobility).
2015

Executia comportamentelor
Calea de executie a firului unui
agent este:
1. Initializarea agentului: setup()
2. Daca nu s-a apelat doDelete() se
merge la pasul urmator, altfel se
apeleaza implicit takeDown(),
dupa care executia se termina.
3. Se determina urmatorul
comportament activ b din lista
comportmentelor active
4. Se executa metoda sa action()
5. Se testeaza terminarea cu done().
Daca done() intoarce fals atunci se
trece la pasul 2, altfel se trece la
pasul urmator
6. Se elimina b din lista
comportamentelor active si se
revine la pasul 2
Daca nu exista comportamente
active firul agentului intra in
“sleep”. 2015
Comportament ONE-SHOT
• Un comportament ONE-SHOT se executa intr-un singur pas. Acest lucru
inseamna ca metoda sa action() se executa o singura data.
• Acest tip de comportament este implementat de clasa:
jade.core.behaviours.OneShotBehaviour
• Metoda done() a comportamentelor ONE-SHOT intoarce true.
• Definirea unui astfel de comportament se face convenabil prin extinderea
clasei OneShotBehaviour astfel:
public class MyOneShotBehaviour extends OneShotBehaviour {
public void action() {
// perform operation X
}
}
• In acest exemplu operatia X se va executa o singura data.

2015

Comportament ciclic
• Un comportament ciclic nu se termina niciodata. Metoda sa action()
executa aceleasi operatii de fiecare data cand este apelata.
• Acest tip de comportament este implementat de clasa:
jade.core.behaviours.CyclicBehaviour
• Metoda done() a comportamentelor ciclice intoarce false.
• Definirea unui astfel de comportament se face convenabil prin extinderea
clasei CyclicBehaviour astfel:
public class MyCyclicBehaviour extends CyclicBehaviour {
public void action() {
// perform operation Y
}
}
• In acest exemplu operatia Y se va executa repetat, pana la terminarea
agentului caruia i s-a asignat comportamentul ciclic respectiv.
2015
Comportament generic
• Un comportament generic contine o variabila de stare ce determina executia unor operatii
diferite in functie de valoarea sa curenta. Un comportament generic se termina la
intalnirea unui anumite conditii.
• Se considera urmatorul exemplu de comportament ce se executa in 3 pasi:
public class ThreeStepBehaviour extends Behaviour {
private int step = 0;
public void action() {
switch (step) {
case 0:
// perform operation X
step++; break;
case 1:
// perform operation Y
step++; break;
case 2:
// perform operation Z
step++; break;
}
}
public boolean done() {
return step == 3;
}
} 2015

Initializarea si terminarea comportamentelor


• Toate comportamentele mostenesc metodele onStart() si onEnd() ale
clasei Behaviour.
• onStart() se executa o singura data inaintea primul apel al metodei
action() a unui comportament.
• onEnd() se executa o singura data dupa ce metoda done() a unui
comportament a intors valoarea true.
• Un comportament poate fi terminat brusc – abortat prin apelul metodei
removeBehaviour() a clasei Agent. In aceasta situatie metoda onEnd() nu
va fi apelata. Ea este apelata doar cand comportamentul se termina in mod
normal.
• Orice comportament dispune de o variabila membru myAgent ce indica
agentul ce executa comportamentul respectiv.
• Dupa executarea unui comportament, daca se doreste executia sa pentru a
doua oara, trebuie intai apelata metoda sa reset().

2015
Planificarea temporala a operatiilor (I)
• Clasa WakerBehaviour permite planificarea executiei unei operatii la expirarea unei
constante de timp (in milisecunde) sau a unei date limita, precizate prin constructor:
public WakerBehaviour(Agent a, java.util.Date wakeupDate);
public WakerBehaviour(Agent a, long timeout);
• Operatia ce trebuie executata este specificata prin definirea metodei abstracte onWake().
Dupa executarea acestei metode executia comportamentului se termina.
public class WakerAgent extends Agent {
protected void setup() {
System.out.println("Adding waker behaviour");
addBehaviour(new WakerBehaviour(this, 10000) {
protected void onWake() {
// perform operation X
}
} );
}
}
• In acest exemplu, operatia X este executata la 10 secunde dupa afisarea mesajului
“Adding waker behaviour”
2015

Planificarea temporala a operatiilor (II)


• Clasa TickerBehaviour permite planificarea executiei repetate a unei operatii la expirarea
unei constante de timp (in ms) precizata prin constructor:
public TickerBehaviour(Agent a, long period);
• Operatia ce trebuie executata este specificata prin definirea metodei abstracte onTick().
Executia unui comportament TickerBehaviour nu se termina decat atunci cand
comportamentul este eliminat din lista de comportamente a agentului sau se executa
explicit metoda sa stop().
public class TickerAgent extends Agent {
protected void setup() {
System.out.println("Adding ticker behaviour");
addBehaviour(new TickerBehaviour(this, 10000) {
protected void onTick() {
// perform operation Y
}
} );
}
}
• In acest exemplu operatia Y este executata din 10 in 10 secunde.
2015
Comunicarea intre agenti
• Se bazeaza pe transferul asincron de mesaje si este compatibila cu
specificatiile FIPA.
• Fiecare agent dispune de o cutie postala – coada de mesaje, unde
primeste mesajele transmise de alti agenti. La fiecare primire a unui mesaj
in coada agentul receptor este notificat corespunzator. Cu toate acestea,
decizia daca si cand agentul va prelua mesajul din coada apartine
programatorului agentului.

2015

Structura unui mesaj


• Structura unui mesaj este compatibila cu definitia FIPA ACL si contine campurile:
– sender – expeditorul mesajului
– receivers – lista destinatarilor
– performative – actul comunicativ ce indica intentia expeditorului. De exemplu: (i) REQUEST
arata ca expeditorul doreste ca destinatarul sa execute o actiune; (ii) INFORM arata ca
expeditorul doreste ca destinatorul sa ia la cunostinta un anumit fapt; (iii) PROPOSE sau CFP
arata ca expeditorul doreste sa intre intr-o negociere cu destinatarul, etc.
– content – descrie continutul informational al mesajului. Poate fi de exemplu o descriere a
actiunii care trebuie executata de un mesaj REQUEST, un fapt care transmis printr-un mesaj
INFORM, etc.
– language – descrie sintaxa folosita pentru exprimarea continutului. Atata expeditorul cat si
destinatarul trebuie sa poata codifica/decodifica expresiile conforme cu aceasta sintaxa
– ontology – descrie vocabularul simbolurilor folosite in exprimarea continutului. Atata
expeditorul cat si destinatarul trebuie sa asocieze aceeasi semantica pentru simbolurile folosite
in schimbul de mesaje
– Campuri aditionale necesare pentru a putea controla mai multe conversatii concurente –
conversation-id, constrangeri si specificatii de primire a unui raspuns – reply-with, in-reply-to,
reply-by, etc.
• Un mesaj JADE este o instanta a clasei jade.lang.acl.ACLMessage. Ea dispune de
metode get si set pentru accesararea tuturor campurilor specifice formatului FIPA ACL.
• Tipurile actelor comunicative sunt definite prin constante in clasa ACLMessage.
2015
Trimiterea unui mesaj
• Trimiterea unui mesaj presupune crearea mesajului si expedierea
mesajului.
• Crearea unui mesaj presupune crearea unei instante a clasei ACLMessage
si apoi setarea diverselor campuri ale mesajului. Foarte importante sunt
specificarea destinatarului cu metoda addReceiver() a clasei ACLMessage
si specificarea continutului cu metoda setContent() a clasei ACLMessage.
• Expedierea unui mesaj se face cu metoda send() a clasei Agent.
• In urmatorul exemplu se trimite un mesaj INFORM catre agentul Ionel.
ACLMessage msgTx = new ACLMessage(ACLMessage.INFORM);
msgTx.addReceiver(new AID("Ionel", AID.ISLOCALNAME));
msgTx.setLanguage("Romana");
msgTx.setOntology("Saluturi");
msgTx.setContent("Buna ziua");
send(msgTx);

2015

Receptionarea unui mesaj


• Receptionarea unui mesaj presupune ca agentul sa preia mesajul din
coada sa de mesaje. Pentru aceasta se foloseste metoda receive() a clasei
Agent.
• Executia metodei receive() presupune preluarea primului mesaj
disponibil din coada de meaje, mesajul fiind eliminat din coada si
returnat. Daca nu exista mesaje in coada metoda receive() returneaza
valoarea null.
• Preluarea unui mesaj din coada se face cu urmatorul sablon de cod:
ACLMessage msg = receive();
if (msg != null) {
// Process the message
}
• Atragem atentia ca receptia unui mesaj cu metoda receive() nu este cu
blocare. Metoda returneaza imediat fie primul mesaj disponibil in coada,
fie valoarea null.
2015
Blocarea unui comportament in asteptarea unui mesaj (I)
• Uzual, se definesc comportamente care realizeaza receptionarea de mesaje
si prelucreaza aceste mesaje. Un astfel de comportament ruleaza in mod
continuu (este ciclic) si la fiecare executie a metodei action() verifica daca
s-a receptionat un mesaj, in caz afirmativ realizand procesarea sa.
• Testarea continua a receptiei unui mesaj este extrem de consumatoare de
timp. Ar trebui ca un comportament ce receptioneaza si prelucreaza
mesaje sa se execute numai in cazul primirii unui nou mesaj.
• Pentru a se obtine acest efect se poate folosi metoda block() a clasei
Behaviour. Acest apel realizeaza “blocarea” comportamentului respectiv,
acest lucru insemnand ca ea nu va mai fi planificata pentru executie de
catre agent.
• Atentie, block() nu este un apel “cu blocare” ! La receptia unui nou mesaj
in coada de mesaje a agentului toate comportamentele blocate devin
automat active fiind planificate pentru executie astfel incat au sansa
preluarii si procesarii noului mesaj primit.

2015

Blocarea unui comportament in asteptarea unui mesaj (II)


• Metoda action() a unui comportament ce asteapta receptionarea
unui mesaj se va programa astfel:
public void action() {
ACLMessage msg = myAgent.receive();
if (msg != null) {
// Message received. Process it
...
}
else {
block();
}
}

2015
Filtrarea mesajelor (I)
• In aplicatii un agent poate fi pus in situatia de a procesa numai mesajele
de un anumit tip. De exemplu un agent interesat in cumpararea de
calculatoare poate primi propuneri de la potentiali vanzatori prin mesaje
PROPOSE. In acest fel el va trebui sa filtreze mesajele PROPOSE din
multimea tuturor mesajelor primite.
• Filtrarea mesajelor la receptie se poate face prin speificarea unui tipar de
mesaj – message template ca parametru al metodei receive().
• Un tipar de mesaj este o instanta a clasei jade.lang.acl.MessageTemplate.
Aceasta clasa dispune de o multime de metode factory pentru crearea de
diverse tipare de mesaje.
• Spre exemplu, crearea unui tipar pentru filtrarea mesajelor cu un anumit
act comunicativ se poate face cu urmatoarea metoda factory:
private MessageTemplate MessageTemplate.MatchPerformative(int performative);

2015

Filtrarea mesajelor (II)


import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
public class SimpleFilteringAgent extends Agent {
public void setup() {
System.out.println("Hello. My name is "+getLocalName());
addBehaviour(new CyclicBehaviour() {
private MessageTemplate mt =
MessageTemplate.MatchPerformative(ACLMessage.PROPOSE);
public void action() {
System.out.println("Incerc sa preiau un nou mesaj PROPOSE");
ACLMessage msgRx = receive(mt);
if (msgRx != null) {
System.out.println("Un nou mesaj PROPOSE:\n"+msgRx);
}
else {
block();
}
}
});
}
} 2015
Receptionarea unui mesaj cu blocare
• Clasa Agent dispune si de o metoda pentru receptionarea unui mesaj cu
blocarea apelului: blockingReceive(). Un apel blockingReceive() nu
intoarce o valoare pana ce agentul receptioneaza un mesaj (exista si o
versiune cu filtrare ce asteapta cu blocare receptionarea unui mesaj
conform cu un tipar).
• Metoda blockingReceive() realizeaza blocarea firului de executie al
agentului. In acest fel se blocheaza executia tuturor celorlalte
comportamente ale agentului pana la deblocarea apelului curent.
• Din acest motiv se recomanda folosirea metodei blockingReceive() doar in
partea de initializare (corpul metodei setup()) sau de finalizare a executiei
(corpul metodei takeDown()) a unui agent.
• Pentru receptionarea mesajelor in cadrul comportamentelor se recomanda
combinatia receive() si block().

2015

Serviciul de pagini aurii (I)


• In aplicatiile uzuale agentii trebuie sa descopere dinamic ce agenti din sistem ar
putea sa le ofere anumite servicii. Astfel, intr-un sistem de comert electronic
agentii cumparatori pot descoperi ce agenti vanztori exista si sunt activi la un
moment dat pentru a se angaja in relatii de tranzactionare de produse cu acestia.
• Un serviciu de “pagini aurii” – yellow pages permite agentilor sa-si publice
descrierile unuia sau mai multor servicii pe care le pot oferi altor agenti astfel incat
acestia sa le poata descoperi si folosi cat mai usor.

2015
Serviciul de pagini aurii (II)
• Orice agent poate publica descrieri de servicii si poate cauta (descoperi)
servicii. Inregistrarile, anularile inregistrarior, actualizarile si cautarile pot
fi efectuate in orice moment de-alungul ciclului de viata al unui agent.
• Serviciul de “pagini aurii” din JADE respecta cerintele FIPA, fiind
furnizat de un agent specializat numit DF. Orice platforma gazduieste un
agent DF implicit cu numele local df@nume-platforma. Pot fi creati mai
multi agenti DF (incluzan agentul implicit) si ei pot fi angajati intr-o
federatie pentru a oferi un catalog distribuit de “pagini aurii”.
• Comunicarea cu DF se poate realiza prin mesaje ACL folosind un limbaj
de continut adecvat – de exemplu SL0 si o ontologie – de exemplu
ontologia FIPA-agent-management, conform specificatiilor FIPA.
• Pentru simplificarea interactiunilor cu DF JADE furnizeaza o clasa
speciala numita jade.domain.DFService cu ajutorul careia este posibil sa
se publice si sa se caute servicii prin intermediul unei API specializate.
2015

Publicarea serviciilor
• Un agent care doreste sa publice unul sau mai multe servicii
trebuie sa furnizeze agentului DF o descriere ce include: (i)
AID-ul sau; (ii) lista serviciilor furnizate; si optional (iii) lista
limbajelor si ontologiilor pe care ceilalti agenti trebuie sa le
foloseasca la interactiunea cu acel agent.

• O descriere de serviciu va include (i) tipul serviciului; (ii)


numele serviciului; (iii) limbajele si ontologiile necesare la
folosirea serviciului; (iv) o multime de proprietati ale
serviciului ca lista perechi cheie-valoare.

• Pentru reprezentarea acestor abstractii JADE furnizeaza


clasele: DFAgentDescription, ServiceDescription, Property
incluse in pachetul jade.domain.FIPAAgentManagement.
2015
Serviciu de “vanzare carti” (I)
• Crearea si inregistrarea in “pagini aurii” a unui
serviciu de vanzare carti:
– Crearea unei descrieri a agentului pt DF: DFAgentDescription
– Crearea uneia / mai multor descrieri de serviciu: ServiceDescription
oferite de agent
– Crearea uneia / mai multor proprietati cheie-valoare asociate fiecarei
descrieri: Property
– Inregistrarea proprietatilor la descrierea serviciului: metoda
addProperties(Property) a clasei ServiceDescription
– Inregistrarea descrierilor de serviciu la descrierea agentului respectiv:
metoda addServices(ServiceDescription) a clasei
DFAgentDescription

2015

Serviciu de “vanzare carti” (II)


import jade.core.Agent;
import jade.domain.FIPAAgentManagement.*;
import jade.domain.*;
public class ServiceAgent extends Agent {
protected void setup() {
// Register the book-selling service in the yellow pages
DFAgentDescription dfd = new DFAgentDescription();
dfd.setName(getAID());
ServiceDescription sd = new ServiceDescription();
sd.setType("Book-selling"); sd.setName(getLocalName()+"-Book-selling");
Property sdp = new Property();
sdp.setName("Role"); sdp.setValue("Seller");
sd.addProperties(sdp);
dfd.addServices(sd);
try { DFService.register(this, dfd);}
catch (FIPAException fe) { fe.printStackTrace(); }
}
protected void takeDown() {
// Deregister from the yellow pages
try { DFService.deregister(this); }
catch (FIPAException fe) { fe.printStackTrace(); }
}
} 2015
Cautarea serviciilor (I)
• Un agent ce doreste sa caute servicii furnizate de alti agenti trebuie sa
furnizeze agentului DF un tipar – template. Conform FIPA, o descriere de
serviciu se potriveste cu tiparul daca campurile specificate in cadrul
tiparului sunt prezente si in descrierea serviciului si au aceleasi valori.
• Pentru cautarea agentilor care ofera un serviciu ce se potriveste cu tiparul se
poate folosi metoda statica search() a clasei DFService:
public static DFAgentDescription[] search(Agent a, AID dfName,
DFAgentDescription dfd, SearchConstraints cnts) throws FIPAException;
public static DFAgentDescription[] search(Agent a, DFAgentDescription dfd)
throws FIPAException;
• Versiunea completa a metodei search() are 4 parametrii:
– Agent a – este agentul care transmite cererea de cautare in DF
– AID dfName – este numele agentului DF in care se face cautarea
– SearchConstraints cnts – reprezinta constrangerile de cautare pentru a restrange
numarul de rezultate
– DFAgentDescription dfd – reprezinta tiparul de cautare
• Versiunea simplificata cu 2 parametrii:
– Realizeaza cautarea in agentul DF implicit
– Se folosesc constrangerile implicite de cautare, ce sunt nule conform FIPA
2015

Cautarea serviciilor (II)


import jade.core.Agent;
import java.util.Vector;
import jade.core.behaviours.TickerBehaviour;
import jade.domain.FIPAAgentManagement.*;
import jade.domain.*;
public class SearcherAgent extends Agent {
private Vector sellerAgents = new Vector(); // List of matching agents
protected void setup() {
// Update the list of seller agents every minute
addBehaviour(new TickerBehaviour(this, 60000) {
protected void onTick() {
DFAgentDescription template = new DFAgentDescription();
ServiceDescription sd = new ServiceDescription();
sd.setType("Book-selling");
template.addServices(sd);
try {
DFAgentDescription[] result = DFService.search(myAgent,template);
sellerAgents.clear();
for (int i = 0; i < result.length; ++i) {
sellerAgents.addElement(result[i].getName());
}
}
catch (FIPAException fe) { fe.printStackTrace();}
}
} );
}
}
2015
Compunerea comportamentelor
• In situatiile in care un agent are de realizat sarcini complexe ce implica
executia mai multor pasi si eventual interactiunea cu unul sau mai multi
agenti nu este convenabil sa se specifice logica sarcinii prin metoda
action() dintr-un singur comportament complicat.
• O metoda mai simpla si mai clara oderita de JADE este compunerea
comportamentelor – crearea de sarcini complexe prin compunerea unor
comportamente simple.
• Crearea de comportamente compuse se realizeaza cu clasa abstracta
CompositeBehaviour:
public class jade.core.behaviours.CompositeBehaviour {
protected abstract boolean
checkTermination(boolean currentDone,
int currentResult);
protected abstract void scheduleFirst();
protected abstract void scheduleNext(boolean currentDone,
int currentResult);
protected abstract Behaviour getCurrent();
}
2015

Clasa CompositeBehavior
• Un CompositeBehaviour contine un numar de subcomportamente. La
primirea controlului ea executa unul dintre ele in functie de o anumita
politica.
• Politica este stabilita de metodele abstracte:
– scheduleFirst() – stabileste ce subcomportament trebuie executat la inceput si
– scheduleNext() – stabileste ce subcomportament trebuie executat la pasul urmator.
• Terminarea este semnalata cand apelul metodei checkTermination()
intoarce true.
• Parametrul currentDone indica daca subcomportamentul curent s-a
terminat (true) sau nu, iar currentResult este valoarea returnata de acesta
(daca s-a terminat) prin metoda onEnd().
• Metoda getCurrent() intoarce subcomportamentul curent planficat pentru
executie.

2015
Schema de compunere a comportamentelor
Schema de executie generica a
metodei action() a unui
comportament compus.

2015

Comportament secvential (I)


• Clasa SequentialBehaviour
implementeaza un comportament
compus cu o politica de executie
secventiala a subcomportamentelor
sale. Executia incepe cu executia
primului subcomportament pana
cand acesta se termina (metoda sa
done() intoarce true), si continua cu
al doilea, etc. Cand ultimul
subcomportament se termina
executia intregului comportament se
termina.
• Adaugarea subcomportamentelor
unui comportament
SequentialBehaviour se realizeaza
cu metoda addSubBehaviour().
Ordinea in care sunt secventializate
subcomportamentele este ordinea in
care ele sunt adaugate la
comportamentul
SequentialBehaviour.
2015
Comportament secvential (II)
import jade.core.*;
import jade.core.behaviours.*;
public class SequentialAgent extends Agent {
protected void setup() {
SequentialBehaviour threeStepBehaviour = new SequentialBehaviour();
threeStepBehaviour.addSubBehaviour(new OneShotBehaviour() {
public void action() {
// perform operation X
System.out.println("Operation X");
}
} );
threeStepBehaviour.addSubBehaviour(new OneShotBehaviour() {
public void action() {
// perform operation Y
System.out.println("Operation Y");
}
} );
threeStepBehaviour.addSubBehaviour(new OneShotBehaviour() {
public void action() {
// perform operation Z
System.out.println("Operation Z");
}
} );
addBehaviour(threeStepBehaviour);
}
} 2015

Comportament paralel (I)


• Clasa ParallelBehaviour implementeaza un comportament
compus cu o politica de executie paralela a
subcomportamentelor sale. Planificarea sarcinilor agentilor in
JADE este cooperativa si nepreemtiva. Acest lucru inseamna
ca la invocarea metodei action() a unui comportament compus
paralel se va executa metoda action() a subcomportamentului
curent si se va trece la comportamentul urmator, indiferent
daca subcomportamentul curent s-a terminat sau nu. In acest
fel se realizeaza executia intretesuta a subcomportamentelor
planficate pentru executie in paralel.
• Adaugarea subcomportamentelor unui comportament
ParallelBehaviour se realizeaza cu metoda
addSubBehaviour().

2015
Comportament paralel (II)
• Un comportament compus paralel se poate termina: (i) fie cand
toate subcomportamentele sale s-au terminat; (ii) fie cand cel
putin unul dintre comportamentele sale s-a terminat.
• Politica de terminare se poate specifica la crearea
comportamentului prin intermediul unui parametru special al
constructorului clasei ParallelBehaviour ce poate avea una
dintre valorile:
– ParallelBehaviour.WHEN_ALL ce indica terminrea la terminarea
tuturor subcomportamentelor
– ParallelBehaviour.WHEN_ANY cc indica terminarea la terminarea
primului subcomportament.
• Varianta WHEN_ANY se poate folosi pentru a specifica
terminarea fortata a unei sarcini in cazul in care ea nu se
finalizeaza intr-un timp predefinit – timeout. In acest caz se
compune paralel acel comportament cu un comportament
WakerBehaviour. 2015

Comportament paralel (III)


public class ParallelAgent extends Agent {
class CounterBehaviour extends Behaviour {
private int crtStep = 0;
private int noOfSteps;
private String name;
protected CounterBehaviour(int n,String name) {
this.name = name; noOfSteps = n;
}
public void action() {
if (crtStep < noOfSteps) {
System.out.println(name+": Step "+crtStep); crtStep++;
}
}
public boolean done() { return crtStep == noOfSteps; }
public int onEnd() {
System.out.println(name+ " terminated."); return 1;
}
}
protected void setup() {
ParallelBehaviour threeBehaviours =
new ParallelBehaviour(ParallelBehaviour.WHEN_ALL);
threeBehaviours.addSubBehaviour(new CounterBehaviour(40,"A"));
threeBehaviours.addSubBehaviour(new CounterBehaviour(50,"B"));
threeBehaviours.addSubBehaviour(new CounterBehaviour(30,"C"));
addBehaviour(threeBehaviours);
}
} 2015
Protocoale de interactiune
• Protocol de interactiune (IP) – interaction protocol = un set predefinit de
schimburi de mesaje intre o multime de agenti ce defineste un sablon de
comunicare independent de domeniul de aplicatie, ce poate fi refolosit in
diverse situatii.
• FIPA defineste o multime de PI bazate pe schimburi de mesaje ACL. O
parte sunt disponibile si in JADE.
• Un caz tipic ce necesita folosirea unui PI standard este delegarea sarcinilor.
Un coordonator trebuie sa selecteze un actor catre care sa delege executia
unei sarcini, dintr-un grup de actori ce au toti capabilitatea de a realiza
sarcina respectiva. Cateva scenarii de aplicare:
– Un server de imprimare trebuie sa selecteze imprimanta spre care sa trimita o sarcina
de imprimare din multimea de imprimante disponibile in functie de incarcarea curenta
a lor (numarul de sarcini de imprimare pe care le are fiecare in coada)
– Un agent cumparator trebuie sa aleaga oferta cea mai avantajoasa de la un agent
vanzator in situatia in care mai multi agenti vanzatori au disponibil spre vanzare
produsul dorit de agentul cumparator.
• Alte cazuri ce necesita folosirea unor PI standard sunt: licitatii, negocieri,
inscrierea pentru primirea de anunturi, etc.
2015

Protocolul FIPA-Contract-Net (I)


1. Initiatorul solicita m propuneri de la alti agenti
numiti participanti printr-un mesaj CFP.
2. Participantii ce primesc cererea genereaza n
raspunsuri. Dintre acestea i ≤ n sunt refuzuri
(REFUSE) si j = n – i sunt propuneri (PROPOSE).
3. Dupa scurgerea unui timp limita (specificat ca
parametru al mesajului CFP), initiatorul evalueaza
cele j propuneri primite si selecteaza zero, unul sau
mai multi agenti pentru realizarea sarcinii.
Propunerile primite dupa termenul limita sunt
automat rejectate cu motivul depasirii timpului limita.
4. Cei l ≤ j agenti selectati sunt anuntati cu un mesaj
ACCEPT-PROPOSAL. Cei k agenti ramasi sunt
instiintati ca nu au fost selectati cu REJECT-
PROPOSAL, l = j – k.
5. Acceptul unui propuneri creaza o obligatie din
partea executantului de realizare a sarcinii. La
terminarea sarcinii, un participant va transmite
initiatorului un mesaj de terminare ce poate fi
INFORM (INFORM-DONE sau INFORM-RESULT)
in caz de succes sau FAILURE in caz de esec.

2015
Protocoale de interactiune in JADE (I)
• Clasele ce ofera suport pentru implementarea PI standard in JADE se
gasesc in pachetul jade.proto.
• In cadrul unei interactiuni guvernata de un PI un agent poate avea rolul de
initiator sau de participant – in JADE este numit responder. Din acest
motiv clasele pachetului jade.proto cuprind doua categorii corespunzatoare
celor doua situatii, cu sufixurile Initiator si respectiv Responder. Spre
exemplu, pentru protocolul FIPA-Contract-Net avem clasele:
ContractNetInitiator si ContractNetResponder.
• Aceste clase dispun de metode de apel invers – callback methods ce trebuie
redefinite de programator pentru implementarea logicii specifice
domeniului de aplicatie.
• Un rol intr-o conversatie implica executarea anumitor sarcini, asa ca toate
clasele pentru implementarea PI standard sunt comportamente JADE.
• Constructorii claselor initiator contin un parametru ACLMessage ce
reprezinta mesajul care initiaza protocolul (de exemplu
ContractNetInitiator va primi un mesaj CFP). Toate clasele initiator suporta
atat o interactiune unu-la-unu cat si o interactiune unu-la-multi, depinzand
de numarul de dstinatari specificati in mesajul de initiere. 2015

Protocoale de interactiune in JADE (II)


• Clasele responder sunt in doua versiuni: (i) versiunea ciclica si (ii) versiunea cu
sesiune unica.
• Versiunea ciclica de responder primeste un MessageTemplate in constructor ce
este folosit pentru selectia mesajelor primite de la initiatori. Un responder ciclic
este de obicei adaugat in timpul executiei metodei setup() a unui agent si ramane
activ pe toata durata de viata a agentului. La primirea unui nou mesaj de initiere
ce se potriveste cu tiparul transmis in constructor acesta este prelucrat, se
realizeaza conversatia si apoi procesul se reia cu asteptarea unui nou mesaj de
initiere. In acest fel versiunea ciclica permite tratarea unei singure conversatii la
un moment dat. Spre exemplu, daca un ContractNetResponder primeste doua
mesaje CFP, responderul va realiza intai conversatia initiata de primul CFP
inainte de a-l trata pe al doilea.
• Versiunea cu sesiune unica primeste un mesaj de initiere in constructor,
realizeaza conversatia initiata de acest mesaj si se termina. Spre deosebire de
versiunea ciclica, versiunea cu sesiune unica nu este responsabila pentru
receptionarea mesajului de initiere. Acesta este receptionat de un comportament
extern.

2015
Implementarea unei negocieri folosind CNP
• Se considera un scenariu de comert electronic.
• O multime de vanzatori ofera spre vanzare un produs (de ex. o carte) si
sunt dispusi sa vanda produsul cu conditia oferirii unui pret minim.
• Un cumparator doreste sa cumpere produsul si are la dispozitie un buget
maxim.
• Cumparatorul emite un CFP cu pretul maxim disponibil. Raspund cu
PROPOSE vanzatorii pentru care acest pret maxim depaseste pretul lor
minim, cerand plata valorii initiale propusa de cumparator in CFP. Restul
raspund cu REFUSE. Cumparatorul alege pe unul dintre cei care au
raspuns cu PROPOSE, ii raspunde cu ACCEPT_PROPOSAL, iar la restul
care au raspuns cu PROPOSE le raspunde cu REJECT_PROPOSAL. In
final vanzatorul selectat raspunde cu INFORM confirmand vanzarea
produsului la pretul stabilit.

2015
Servicii Web

Capitolul 9

2015

Introducerea serviciilor Web

• SD sunt compuse dintr-o multitudine de sisteme


eterogene. Tehnologiile SD urmaresc sa ofere metode
pentru integrarea acestor subsisteme intr-un SD. Aceste
metode includ concepte, abstractii, si sabloane care sa
permita integrarea unor subsisteme slab conectate
eterogene intr-un SD.

• Serviciile Web (SW) reprezinta o metoda de integrare a


aplicatiilor “enterprise” ce ia in calcul atat
eterogenitatea componentelor, cat si scala Internet a
retelei.
2015
Definirea serviciilor Web
• Definitie: A Web service is a software system identified by a
URI [RFC 2396], whose public interfaces and bindings are
defined and described using XML. Its definition can be
discovered by other software systems. These systems may then
interact with the Web service in a manner prescribed by its
definition, using XML based messages conveyed by Internet
protocols (http://www.w3.org/TR/wsa-reqs/).
• Proprietati esentiale ale unui SW:
– Poate fi definit: o aplicatie isi poate expune o parte din functionalitate
ca serviciu Web
– Poate fi descris: este suficient ca o aplicatie client sa cunoasca
descrierea sa astfel incat sa-l poata invoca.
– Poate fi descoperit: descrierea poate fi publicata si regasita, in functie
de diverse criterii, prin intermediul unui serviciu de directoare.

2015

Motivarea SW
• Se considera un
scenariu de integrare
de aplicatii B2B:
– Un beneficiar (engl.
customer) comanda
marfuri de la un
furnizor (engl.
supplier).
– Furnizorul le livreaza
din stoc (daca
marfurile exista in
stoc) sau cere ca
marfurile sa fie livrate
de un partener tert
depozit (engl.
warehouse).
@ Alonso et al.2004
2015
Infrastructura si componentele SW
• Un SW este identificat printr-un URI si poate fi accesat de clienti prin
mesaje formatate folosind XML.
• Mesajele sunt incapsulate folosind SOAP (initial acronim pentru Simple
Object Access Protocol) si transmise peste un protocol de transport:
HTTP, SMTP sau TCP.
• Interfetele SW sunt descrise in WSDL (Web Services Description
Language)
• Aplicatiile folosesc SW. Anumite SW au functii generale (orizontale):
securitate, servicii de directoare, coreografie.

@ Colouris et al.2012

2015

Operatiile serviciilor Web


• Un SW ofera o multime de operatii care pot fi invocate
de catre un client din Internet. Operatiile pot fi
furnizate de resurse diverse: aplicatii, obiecte, baze de
date, etc.
• Serverele de Web comerciale: Amazon, Yahoo, Google
si eBay ofera interfete pentru SW prin care clientii pot
avea acces la resursele acestor servere.
• Exista doua metode principial diferite de definire si
acces ale unui serviciu Web:
– Metoda REST (Representational State Transfer)
– Metoda SOAP specifica arhitecturilor orientate pe servicii

2015
Metoda REST
• Metoda REST este inspirata din arhitectura Web-ului si din
specificatiile protocolului HTTP.
• REST este un stil arhitectural pentru sisteme hipermedia
distribuite, propus de Roy Fielding in capitolul 5 al tezei sale
de doctorat in 2000.
• Acest stil arhitectural este caracterizat prin 6 principii:
– Client – server.
– Stateless.
– Cache(able).
– Uniform interface.
– Layered system.
– Code-on-demand (optional).

2015

Client – server
• Principiul modelului client – server este separarea
responsabilitatilor (engl. separation of concerns).
• Clientii sunt responsabili cu partea de interfata cu utilizatorul,
in schimb serverele sunt repsonsabile cu stocarea datelor.
• Avantaje:
– Se imbunatateste portabilitatea interfetei cu utilizatorul pe platforme
multiple
– Creste scalabilitatea serverului prin simplificarea componentelor sale
– Cele doua tipuri de componente pot evolua separat, lucru specific
cerintelor SD actuale de a putea evolua la scala Internet-ului in
domenii organizationale multiple

@ Fielding.2000

2015
Stateless
• Comunicarea dintre client si server este fara stare, in sensul ca serverul nu pastreaza
starea interactiunii cu clientul.
• Rezulta ca fiecare cerere de la client catre server trebuie sa contina toata informatia
necesara intelegerii cererii, intrucat nu exista informatie de stare stocata pe server.
• Avantaje:
– Vizibilitatea este imbunatatita. Un sistem de monitorizare nu va avea nevoie de alte informatii,
pe langa cerere, pentru analiza completa a cererii.
– Fiabilitatea este imbunatatita deoarece se simplifica recuperarea din erori partiale.
– Scalabilitatea serverului creste deoarece operarea acestuia este simplificata.
• Dezavantaje:
– Scade performanta retelei, din cauza transmisiei repetate a datelor.
– Serverul pierde controlul asupra consistenta aplicatiei, ce va depinde de corectitudinea
implementarii clientului

@ Fielding.2000

2015

Cache(able)
• Clientii pot stoca in cache raspunsurile. Pentru aceasta,
continutul unui raspuns poate fi marcat explicit ca fiind
cacheable sau not-cacheable.
• Avantaje:
– Creste eficienta, prin eliminarea anumitor interactiuni
– Creste scalabilitatea si gradul de satisfactie al utilizatorului
• Dezavantaje
– Scade fiabilitatea, in cazul in care datele salvate in cache (engl. stale
data) sunt expirate si difera semnificativ de datele care ar putea fi
obtinute printr-o interactiune directa.

@ Fielding.2000

2015
Uniform interface
• Simplifica arhitectura si asigura decuplarea implementarii de
interfetele serviciilor.
• Acest principiu se bazeaza pe constrangerile:
– Identificarea resurselor
– Manipularea resurselor prin intermediul reprezentarilor lor
– Mesaje auto-descriptive, adica contin toata informatia necesara
procesarii lor
– Hipermedia este motorul starii aplicatiei.

@ Fielding.2000

2015

Layered System
• Arhitectura este compusa din nivele ierarhice astfel incat un
client nu va putea determina daca este conectat direct la un
server final sau la un intermediar.
• Folosirea serverelor intermediare permite:
– Cresterea scalabilitatii prin echilibrarea incarcarii, asemanator cu o
arhitectura de procesure pe flux de tip pipe-and-filter.
– Asigurarea unor politici de securitate privind datele care traverseaza
bariere organizationale.

@ Fielding.2000

2015
Code-on-demand
• Arhitectura permite extinderea functionalitatii clientului prin
descarcarea de cod sursa sau binar.
• Aceasta facilitate permite imbunatatirea extensibilitatii
sistemului, dar reduce vizibilitatea, fiind un principiu optional.

@ Fielding.2000

2015

Metoda SOAP
• Metoda SOAP este inspirata din RPC si RMI. Conform
metodei SOAP, un SW expune o interfata care este descrisa
folosind WSDL.
• Standardele Web referitoare la SOAP si WSDL sunt parte a
Web Services Activiy: http://www.w3.org/2002/ws/
• Apelurile clientilor trebuie sa fie conforme cu specificatia
interfetei SW, similar cu apelul procedurilor si metodelor din
limbajele de programare.
• Metoda SOAP aduce in plus fata de RMI:
– Identificarea SW prin URI, ca orice resursa Web
– Reprezentarea in XML a mesajelor interschimbate de clienti si servere
– Transportul mesajelor peste protocoalele Internet, cum sunt HTTP sau
SMTP

2015
Introducere in SOAP
• W3C a lansat SOAP in 1999. Versiunea curenta este 1.2.
• SOAP acopera 4 aspecte:
– Un format de mesaje pentru communicare intr-un singur sens ce
descrie reprezentarea unui mesaj intr-un document XML
– O descriere cum un mesaj SOAP (documentul XML reprezentat de
mesaj) ar trebui transportat folosind HTTP sau SMTP
– Un set de reguli ce trebuie urmate la procesarea unui mesaj SOAP si o
clasificare simpla a entitatilor implicate in procesarea unui mesaj
SOAP. Se specifica ce parti ale mesajelor ar trebui citite de care dintre
entitati si cum trebuie reactionat la un continut neinteles
– Un set de conventii cum sa se transforme un apel RPC intr-un mesaj
SOAP si reciproc, respectiv cum ar trebui sa se implementeze un stil
RPC de interactiune (clientul creaza un apel RPC, acesta este tradus
intr-un mesaj SOAP, inaintat si transformat intr-un apel RPC la server,
raspunsul serverului este convertit in mesaj SOAP, transmis clientului,
si returnat clientului ca urmare a apelului RPC)
2015

Mesaje SOAP
Plic SOAP
• Un mesaj SOAP este incapsulat intr-
un “plic” ce contine datele care Antet SOAP
trebuie transmise.
• Plicul are asociata o informatie Element antet
necesara pentru transportul
mesajului la intermediari si la
receptorul final. Corp SOAP
• Continutul unui mesaj are 2 parti:
– Antet (engl. header) partitionat in Element corp
blocuri sau elemente. Este optional. Se
adreseaza infrastructurii de SW.
– Corp (engl. body sau payload)
partitionat in blocuri sau elemente. Este
obligatoriu. Se adreseaza aplicatiei.
2015
Structura unui mesaj SOAP
<?xml version='1.0' ?>
<env:Envelope
xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Header>
...
</env:Header>
<env:Body>
...
</env:Body>
</env:Envelope>
• Antetul este marcat cu Header si corpul este marcat cu Body.
• Mesajul SOAP este marcat cu Envelope.
• Continutul mesajului depinde de stilul de construire.

2015

Exemplu
• Sa consideram un mesaj SOAP intr-o aplicatie Web pentru
rezervarea unui bilet de avion.
• Un client doreste sa rezerve un bilet pentru un zbor cu un traseu
specificat, printr-o aplicatie de rezervare. Aplicatia de rezervare
contacteaza sistemul de rezervari al unei agentii folosind
SOAP.
• Aplicatia clientului transmite mesajul cu preferintele rezervarii
clientului.
• Sistemul de rezervari raspunde cu o multime de optiuni ce
satisfac preferintele clientului.
• Clientul isi alege un zbor convenabil si furnizeaza detaliile de
plata, printr-un mesaj SOAP transmis de aplicatia de rezervare.
• Sistemul de rezervari raspunde prin confirmarea sau infirmarea
realizarii platii. 2015
Stiluri de mesaje SOAP
• Construirea unui mesaj SOAP este influentata de:
– Stilul de interactiune
– Regulile de codare (engl. encoding rules)
• In functie de stilul de interactiune avem:
– Stilul document
– Stilul RPC
• Stilul document presupune ca aplicatiile ce comunica prin SOAP sa se
puna de acord asupra structurii documentelor interschimbate. Corpul
mesajului SOAP va contine un document XML care reprezinta mesajul.
• Stilul RPC presupune existenta de mesaje cerere si mesaje raspuns,
similar unui apel RPC.
– Mesajul cerere contine: (i) numele procedurii (operatiei) invocate si (ii) parametrii de
intrare.
– Mesajul de raspuns contine: (i) rezultatul operatiei si (ii) parametrii de iesire.

2015

Reguli de codare
• Definesc modul de reprezentare in XML al unei entitati sau structuri de
date. De exemplu, un produs se poate reprezenta in XML intr-o mare
varietate de moduri:
<ProductItem> <ProductItem <ProductItem name=“…”
<name>…</name> name=“…” <type>…</type>
<type>…</type> type=“…” <make>…</make>
<make>…</make> make=“…” </ProductItem>
</ProductItem> />

• Pentru interoperare, serverul si clientul trebuie sa se puna de acord asupra


regulilor de codare a continutului mesajelor SOAP.
• Exemple de reguli de codare:
– Codare SOAP, definita de SOAP 1.2. Defineste o modalitate de reprezentare in XML
a modelului de date SOAP, definit de SOAP 1.2.
– Codare lieral (engl. literal encoding). Presupune ca aplicatiile care interactioneaza sa
defineasca de comun acord o schema a documentelor XML interschimbate. Schema
se defineste de regula folosind XML Schema.

2015
Modelul de date SOAP 1.2 - I
• Acest model defineste datele aplicatiei sub forma unui graf
orientat etichetat. Modelul este optional.
• Graful este format din arce si varfuri. Un arc poate sa fie arc
de iesire sau arc de intrare in raport cu un varf.
• Arcele de iesire ale unui varf se disting prin eticheta si/sau
pozitie. Pozitia defineste o relatie de ordine totala pe multimea
arcelor de iesire ale unui varf.
• Etichetele arcelor sunt nume de elemente XML.
• Un varf al grafului are zero sau mai multe arce de iesire. Un
varf fara arce de iesire are asociata optional o valoare lexicala.
• Un varf al grafului poate fi simplu referit sau multiplu referit,
dupa cum are un singur arc de intrare sau mai multe arce de
intrare.
2015

Modelul de date SOAP 1.2 - II


• O data poate sa fie simpla sau compusa.
• O data simpla se reprezinta printr-un graf format dintr-un
singur varf cu o valoare lexicala.
• O data compusa este reprezentata printr-un varf cu zero sau mai
multe arce de iesire.
– Un varf ale carui arce de iesire se disting doar prin etichete se numeste
struct. In acest caz, toate arcele de iesire trebuie sa aiba etichete
diferite.
– Un varf ale carui arce de iesire se disting numai prin pozitie se
numeste array. In acest caz arcele de iesire nu trebuie sa fie etichetate.

2015
Reprezentarea in XML a modelului de date SOAP
• Codarea SOAP defineste un set de reguli prin care modelul de
date SOAP este reprezentat in XML.
• Arcele grafului se reprezinta prin elemente XML. Varful
terminal al unui arc se determina astfel:
– Daca un element XML nu are atribut ref atunci el reprezinta un varf al
grafului iar arcul corespunzator elementului se termina in acel varf.
– Daca un element XML x are atribut ref atunci valoarea y a acestui
atribut trebuie sa fie identica cu atributul id al unui unic element XML
z din plicul mesajului. In acest caz, arcul reprezentat prin x se va
termina intr-un varf al grafului asociat elementului z.
• Valoarea lexicala a unui varf se reprezinta prin textul din nodul
respectiv. Optional, elementul ce contine valoarea respectiva
poate sa aiba atributul nodeType, cu una din valorile simple,
struct sau array.
2015

Mesaje SOAP stil document


• Informatia este incapsulata in mesajul de cerere sau raspuns sub
forma unui document XML.

Plic SOAP Plic SOAP

Corp SOAP Corp SOAP

Document cerere Document raspuns


-parametrii -rezultate

2015
Mesaje SOAP stil RPC
• Informatia unui mesaj de cerere este structurata conform cerintelor RPC
in nume metoda si parametrii.
• Pentru mesajul de raspuns avem numele metodei careia i se adreseaza
raspunsul, o valoare de retur si optional parametrii de iesire.

Plic SOAP Plic SOAP

Corp SOAP Corp SOAP

Nume metoda Nume metoda raspuns

Parametru de intrare 1 Valoare de retur

Parametru de intrare 2 Parametru de iesire 1

... ...

2015

Antetul unui mesaj SOAP stil document


<m:reservation
xmlns:m="http://travelcompany.example.org/reservation"
env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
env:mustUnderstand="true">
<m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
<m:dateAndTime>2001-11-29T13:20:00.000-05:00</m:dateAndTime>
</m:reservation>
<n:passenger
xmlns:n="http://mycompany.example.com/employees"
env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
env:mustUnderstand="true">
<n:name>Costin Badica</n:name>
</n:passenger>
• Se considera mesajul SOAP stil document care specifica cererea de rezervare.
• Antetul SOAP este optional si poate contine meta-informatie despre:
– Rezervare (identificator, data)
– Pasager
• Atributul role cu valoarea next specifica faptul ca mesajul este destinat urmatorului nod
SOAP. Atributul mustUnderstand cu valoarea true inseamna ca nodurile ce proceseaza
mesajul trebuie sa proceseze obligatoriu si antetul mesajului.
2015
Corpul unui mesaj SOAP stil document (cerere)
<p:itinerary
xmlns:p="http://travelcompany.example.org/reservation/travel">
<p:departure>
<p:departing>New York</p:departing>
<p:arriving>Los Angeles</p:arriving>
<p:departureDate>2001-12-14</p:departureDate>
<p:departureTime>late afternoon</p:departureTime>
<p:seatPreference>aisle</p:seatPreference>
</p:departure>
<p:return>
<p:departing>Los Angeles</p:departing>
<p:arriving>New York</p:arriving>
<p:departureDate>2001-12-20</p:departureDate>
<p:departureTime>mid-morning</p:departureTime>
<p:seatPreference/>
</p:return>
</p:itinerary>
• Corpul contine informatie despre intinerariul calatoriei:
– Traseu plecare, traseu intoarcere
– Un traseu are: aeroporturi sursa si destinatie, data, perioada din zi preferata
2015

Mesaj SOAP stil document (raspuns)


<env:Header>
<m:reservation xmlns:m="http://travelcompany.example.org/reservation"
env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
env:mustUnderstand="true">
<m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
<m:dateAndTime>2001-11-29T13:35:00.000-05:00</m:dateAndTime>
</m:reservation>
<n:passenger xmlns:n="http://mycompany.example.com/employees"
env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
env:mustUnderstand="true">
<n:name>Costin Badica</n:name>
</n:passenger>
</env:Header>
<env:Body>
<p:itineraryClarification
xmlns:p="http://travelcompany.example.org/reservation/travel">
<p:departure>
<p:departing>
<p:airportChoices>JFK LGA EWR</p:airportChoices>
</p:departing>
</p:departure>
<p:return>
<p:arriving>
<p:airportChoices>JFK LGA EWR</p:airportChoices>
</p:arriving>
</p:return>
</p:itineraryClarification>
</env:Body>
• Sistemul de rezervare raspunde cerand clarificari asupra aeroporturilor de plecare si de
sosire.
2015
Mesaj SOAP stil document (raspuns la raspuns)
<env:Header>
<m:reservation xmlns:m="http://travelcompany.example.org/reservation"
env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
env:mustUnderstand="true">
<m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
<m:dateAndTime>2001-11-29T13:36:50.000-05:00</m:dateAndTime>
</m:reservation>
<n:passenger xmlns:n="http://mycompany.example.com/employees"
env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
env:mustUnderstand="true">
<n:name>Costin Badica</n:name>
</n:passenger>
</env:Header>
<env:Body>
<p:itinerary
xmlns:p="http://travelcompany.example.org/reservation/travel">
<p:departure>
<p:departing>LGA</p:departing>
</p:departure>
<p:return>
<p:arriving>EWR</p:arriving>
</p:return>
</p:itinerary>
</env:Body>
• Aplicatia de rezervare specifica clarificarile cerute asupra aeroporturilor
de plecare si de sosire.
2015

Scenariu de plata pentru biletul de avion


• Se presupune ca traseul a fost definitivat de comun acord intre
aplicatia de rezervare si sistemul de rezervare si confirmat.
• Plata are loc in contextul tranzactiei de rezervare a biletului de
avion pentru traseul specificat.
• Aplicatia de rezervare furnizeaza numarul rezervarii si numarul
cardului de credit – parametrii in.
• Interactiunea de rezervare si plata intre aplicatia de rezervare si
sistemul de rezervare se modeleaza cu SOAP in stil RPC.
• Invocarea SOAP RPC necesita:
– Adresa nodului SOAP tinta
– Numele metodei
– Numele si valorile argumentelor, numele parametrilor de iesire si al
valorii de retur
2015
Mesaj SOAP stil RPC
<env:Header>
<t:transaction
xmlns:t="http://thirdparty.example.org/transaction"
env:encodingStyle="http://example.com/encoding"
env:mustUnderstand="true" >5</t:transaction>
</env:Header>
<env:Body>
<m:chargeReservation
env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
xmlns:m="http://travelcompany.example.org/">
<m:reservation
xmlns:m="http://travelcompany.example.org/reservation">
<m:code>FT35ZBQ</m:code>
</m:reservation>
<o:creditCard xmlns:o="http://mycompany.example.com/financial">
<n:name xmlns:n="http://mycompany.example.com/employees">
Costin Badica</n:name>
<o:number>123456789099999</o:number>
<o:expiration>2005-02</o:expiration>
</o:creditCard>
</m:chargeReservation>
</env:Body> 2015

Descriere mesaj SOAP stil RPC


• Continutul mesajului din campul Body contine apelul RPC
reprezentat folosind codarea SOAP. Aceasta este reprezentarea
XML a urmatorului graf.
chargeReservation
reservation code
FT35ZBQ

credit card

name
Costin Badica

number

123456789099999

expiration
2005-02
2015
Raspuns la cererea de plata a biletului de avion
• Presupunem ca apelul RPC pentru plata biletului de avion a
fost proiectat sa accepte doi parametrii de iesire – out:
– Un parametru care va contine codul de referinta al rezervarii
– Un URI unde utilizatorul client poate vizualiza detaliile rezervarii.
• Pentru a indica faptul ca avem un mesaj raspuns la cererea RPC
cu metoda chargeReservation, raspunsul va aduaga sufixul
Response la numele metodei din cerere, rezultand metoda
chargeReservationResponse.
• Uneori descrierea RPC permite ca apelul sa intoarca o valoare
printr-un parametru return. In cazul nostru aceasta valoare ne
poate indica faptul ca plata a fost confirmata prin confirmed sau
este in asteptare prin pending.

2015

Mesaj SOAP raspuns stil RPC


<env:Header>
<t:transaction
xmlns:t="http://thirdparty.example.org/transaction"
env:encodingStyle="http://example.com/encoding"
env:mustUnderstand="true">5</t:transaction>
</env:Header>
<env:Body>
<m:chargeReservationResponse
env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
xmlns:m="http://travelcompany.example.org/">
<m:code>FT35ZBQ</m:code>
<m:viewAt>
http://travelcompany.example.org/reservations?code=FT35ZBQ
</m:viewAt>
</m:chargeReservationResponse>
</env:Body>

2015
Mesaj SOAP raspuns stil RPC cu valoare returnata
<env:Header>
<t:transaction
xmlns:t="http://thirdparty.example.org/transaction"
env:encodingStyle="http://example.com/encoding"
env:mustUnderstand="true">5</t:transaction>
</env:Header>
<env:Body>
<m:chargeReservationResponse
env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
xmlns:rpc="http://www.w3.org/2003/05/soap-rpc"
xmlns:m="http://travelcompany.example.org/">
<rpc:result>m:status</rpc:result>
<m:status>confirmed</m:status>
<m:code>FT35ZBQ</m:code>
<m:viewAt>
http://travelcompany.example.org/reservations?code=FT35ZBQ
</m:viewAt>
</m:chargeReservationResponse>
</env:Body>

2015

Procesarea mesajelor SOAP


• Infrastructura SOAP presupune existenta unor noduri de procesare:
– Nodul transmitator, care a initiat mesajul SOAP
– Nodul receptor final, care este destinatarul final al mesajului SOAP
– Nodurile intermediar, care au rolul de aprocesa mesajul SOAP de-alungul rutei sale
de la transmitator la receptor.
• Continutul care trebuie transferat de la transmitator la receptorul final se
afla in elementul Body.
• Informatia aditionala necesara procesarii mesajului de catre intermediari
(informatie despre tranzactie, securitate, etc.) este amplasata in Header.
• Un Header SOAP este compus dintr-unul sau mai multe blocuri. Fiecare
bloc defineste diverse atribute, dintre care anumite atribute sunt definite in
spatiul de nume env. Ele trebuie analizate de nodurile de pe traseul
mesajului SOAP.
– role
– mustUnderstand
– relay
2015
Atributul role
• Acest atribut defineste rolul care trebuie asumat de un nod in
ceea ce priveste procesarea unui mesaj SOAP.

Role absent "none" "next" "ultimateReceiver"

Node

transmitator neaplicabil neaplicabil neaplicabil neaplicabil

intermediar nu nu da nu

destinatar final da nu da da

2015

Atributul mustUnderstand
• Acest atribut poate avea doua valori:
– true = acest lucru inseamna ca un nod caruia ii este destinat acest
bloc, trebuie sa proceseze obligatoriu nodul respectiv conform
semanticii blocului respectiv.
– false = acest lucru inseamna ca procesarea blocului de un nod caruia
ii este destinat acest bloc este optionala.

Nod intermediar Destinatar final


mustUnderstand
"true" procesare obligatorie procesare obligatorie
"false" procesare optionala procesare optionala
absent procesare optionala procesare optionala
2015
Transportul mesajelor SOAP
• Mesajele SOAP pot fi interschimbate folosind o varietate de
protocoale de transport.
• Specificarea modului in care mesajele SOAP sunt transportate
intre nodurile unei rute se numeste legatura SOAP.
• O legatura SOAP trebuie sa rezolve urmatoarele probleme:
– Modul in care un mesaj SOAP este impachetat intr-un protocol de
transport si modul in care este tratat de catre primitivele protocolului
de transport
– Adresarea destinatarului final al mesajului, respectiv rutarea mesajului
catre destinatarul final.
– Sablonul de schimbare a mesajelor (engl. message-exchange-pattern
MEP). Exista doua astfel de sabloane:
• SOAP Request-Response message exchange pattern (foloseste HTTP POST)
• SOAP Response message exchange pattern (foloseste HTTP GET)

2015

Transportul mesajelor SOAP peste HTTP – I


• Sa presupunem ca clientul doreste sa obtina informatie privind
intinerariul de calatorie in format SOAP. Se foloseste SOAP
Response MEP.
• Clientul va emite o cerere HTTP GET cu formatul urmator:

GET /travelcompany.example.org/reservations?code=FT35ZBQ HTTP/1.1


Host: travelcompany.example.org
Accept: text/html;q=0.5, application/soap+xml

• Antetul HTTP Accept specifica faptul ca reprezentarea


preferata a resursei este application/soap+xml.

• Serverul va raspunde cu un raspuns HTTP ce va contine in


corpul sau un mesaj SOAP, prezentat pe slide-ul urmator.
2015
Transportul mesajelor SOAP peste HTTP – II
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset="utf-8"
Content-Length: nnnn

<?xml version='1.0' ?>


<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Header>
<m:reservation xmlns:m="http://travelcompany.example.org/reservation"
env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
env:mustUnderstand="true">
<m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
<m:dateAndTime>2001-11-30T16:25:00.000-05:00</m:dateAndTime>
</m:reservation>
</env:Header>
<env:Body>
...
</env:Body>
</env:Envelope>

2015

Descrierea Serviciilor Web


• Web Services Description Language – WSDL are rolul unui
IDL din middleware-ul pentru RPC si RMI pentru descrierea
SW.
• In plus, WSDL are urmatoarele functii:
– Defineste o modalitate de acces la SW. SW pot fi disponibile folosind
o varietate de protocoale, in timp ce RPC clasic este in general legat de
o platforma middleware, astfel accesul este implicit.
– Defineste locatia unde este disponibil un anumit SW.
– Permite o descriere modulara a operatiilor si a grupurilor de operatii,
ce se potriveste mai bine cu complexitatea ridicata a SW.
• Versiunea curenta este WSDL 2.0. Ea a devenit recomandare in
2007: http://www.w3.org/TR/wsdl20-primer/

2015
Structura WSDL

Specificatie WSDL

• Partea abstracta este identica dpdv Parte abstracta


conceptual cu interfata abstracta tipuri
definita de un IDL
interfete

Parte concreta
• Partea concreta defineste legaturile
legaturi
SW si alte informatii specifice SW.
servicii

2015

Exemplu: sistem de rezervare la hotel – I


• Se considera un sistem de rezervare de camere la un
hotel fictiv GreatH ce ofera functia de verificare a
disponibilitatii unei camere CheckAvailability.
– Clientul specifica:
• Data de intrare (engl. Check-in date)
• Data de iesire (engl. Check-out date)
• Tipul de camera
– Serviciul intoarce:
• Rata camerei, numar real reprezentand pretul in USD, daca exista
disponibilitatea camerei, altfel aceasta valoare este 0
• Eroare daca datele de intrare sunt invalide.
– Servicul accepta un mesaj checkAvailability si returneaza
mesajele checkAvailabilityResponse sau invalidDataFault.
2015
Exemplu: sistem de rezervare la hotel – II
• Serviciul ofera si o functie de rezervare a unei camere
MakeReservation.
– Clientul furnizeaza:
• Numele
• Adresa
• Informatie despre cartela de credit
– Serviciul intoarce:
• Un numar al rezervarii in cazul in care rezervarea s-a efectuat cu
succes
• Un mesaj de eroare daca datele au fosy invalide (de exemplu,
cartela de credit nu este OK).
– Serviciul accepta un mesaj makeReservation si returneaza
mesajele makeReservationResponse sau
invalidCreditCardFault.
2015

Document WSDL vid


<?xml version="1.0" encoding="utf-8" ?>
<description
xmlns="http://www.w3.org/ns/wsdl"
targetNamespace="http://greath.example.com/2004/wsdl/resSvc"
xmlns:tns= "http://greath.example.com/2004/wsdl/resSvc"
. . . >

. . .
</description>
• Elementul radacina al WSDL este description.
• In exemplu nu se asigneaza un nume special pentru spatiul de nume al
elementelor tipice WSDL. Orice element neprefixat cu spatiu de nume
este specific vocabularului WSDL. Spre deosebire de acest exemplu, in
exemplele SOAP am folosit numele env pentru vocabularul SOAP.
• Se defineste apoi spatiul de nume pentru vocabularul folosit la descrierea
serviciului de rezervare prin interfete, legaturi si servicii. Se initializeaza
atat atributul targetNamespace, cat si spatiul de nume tns. Elementele
descrierii serviciului de rezervare vor fi astfel prefixate cu tns.
2015
Partea abstracta a WSDL
• Contine:
– Optional o multime de definitii de tipuri. Aceste tipuri
descriu datele din cadrul mesajelor primite si receptionate de
SW.
– O multime de zero sau mai multe interfete. O interfata
defineste o multime de operatii, similar cu RPC. Fiecare
operatie se caracterizeaza printr-un sablon de schimb de
mesaje (engl. message exchange pattern) – MEP. O operatie
grupeaza o multime de mesaje de cerere si raspuns.

2015

Schema de definire a mesajelor


<?xml version="1.0" encoding="utf-8" ?>
<description
. . .
xmlns:ghns = "http://greath.example.com/2004/schemas/resSvc"
. . . >
. . .
<types>
. . .
</types>
. . .
</description>
• Se defineste un spatiu de nume gbns pentru vocabularul folosit la
descrierea tipurilor de date din mesajele SW.
• Tipurile de date se descriu direct folosind XML Schema in cadrul
elementului types.
• Pentru simplificare, in cadrul acestor definitii se redefineste spatiul de
nume, astfel incat orice element neprefixat cu spatiul de nume sa fie
implicit asociat cu vocabularul tipurilor de date din mesajele SW (v ezi
slide-ul urmator)
2015
Definirea tipurilor de date
<types>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://greath.example.com/2004/schemas/resSvc"
xmlns="http://greath.example.com/2004/schemas/resSvc">
<xs:element name="checkAvailability" type="tCheckAvailability"/>
<xs:complexType name="tCheckAvailability">
<xs:sequence>
<xs:element name="checkInDate" type="xs:date"/>
<xs:element name="checkOutDate" type="xs:date"/>
<xs:element name="roomType" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="checkAvailabilityResponse" type="xs:double"/>
<xs:element name="invalidDataError" type="xs:string"/>
</xs:schema>
</types>
• Aceasta schema defineste trei tipuri de mesaje:
– Mesajul de cerere checkAvailability
– Mesajele de raspuns checkAvailabilityResponse si invalidDataError
2015

Schema de definire a interfetelor


<?xml version="1.0" encoding="utf-8" ?>
<description
. . .
xmlns:wsdlx="http://www.w3.org/ns/wsdl-extensions">
. . .
<types>
. . .
</types>
<interface name = "reservationInterface" >
. . .
</interface>
. . .
</description>
• Elementul interface defineste o interfata abstracta a SW sub forma unei
multimi de operatii. Un SW poate defini mai multe interfete abstracte.
• O operatie reprezinta un tip de interactiune intre un client si SW. O
operatie specifica o multime de mesaje si un sablon de interactiune.
• O operatie poate defini si o multime de erori, impreuna cu mesajele de
eroare corespunzatoare
2015
Definirea operatiilor
<interface name = "reservationInterface" >
<fault name = "invalidDataFault“ element = "ghns:invalidDataError"/>
<operation name="opCheckAvailability"
pattern="http://www.w3.org/ns/wsdl/in-out"
style="http://www.w3.org/ns/wsdl/style/iri"
wsdlx:safe = "true">
<input messageLabel="In“ element="ghns:checkAvailability"/>
<output messageLabel="Out"
element="ghns:checkAvailabilityResponse"/>
<outfault ref="tns:invalidDataFault" messageLabel="Out"/>
</operation>
</interface>
• Elementul fault defineste o eroare, ce poate fi ulterior referita intr-o
operatie. Atributul element defineste elementul de date asociat mesajului
de eroare. Este referit in spatiul de nume ghbs, definit anterior.
• Elementul operation defineste operatia opCheckAvailability. Atributul
pattern defineste modul de interactiune, in-out in acest caz. Atributul style
se refera la stilul operatiei, ce include formatul mesajelor. Atributul
wsdlx:safe cu valoarea true ne indica faptul ca operatia este sigura, in
sensul ca nu implica nici un fel de obligatie pentru client. 2015

Parametrii operatiilor
• Elementul input se foloseste pentru specificarea unui parametru
de intrare ai unei operatii.
• Orice operatie specifica si un MEP, prin atributul pattern.
Atributul messageLabel specifica rolul acestui mesaj in cadru
unei secvente de interactiune dintre client si SW, conforma cu
MEP-ul specificat. In acest caz rolul este In.
• Atributul element specifica tipul de date asociat acestui mesaj,
in spatiul de nume ghns.
• Elementul ouput specifica un parametru de iesire al unei
operatii.
• Elementul outfault specifica un posibil mesaj de eroare ce poate
fi transmit clientului. Fiind vorba de sablonul in-out, daca este
prezent, el va inlocui mesajul in directia out.
2015
Sabloane de schimburi de mesaje
• in-only • Sabloanele robust-* si
– Un mesaj cu eticheta In in directia in *-optional-* pot genera erori.
• robust-in-only Acestea sunt semnalate
– Un mesaj cu eticheta In in directia in asociind un posibil mesaj de
• in-out eroare fiecarui mesaj din
– Un mesaj cu eticheta In in directia in sablon. Un mesaj de roare are
– Un mesaj cu eticheta Out in directia out.. o directie inversa fata de
• in-optional-out mesajul din sablon.
– Un mesaj cu eticheta In in directia in
– Optional un mesaj cu eticheta Out in directia out
• Sabloanele *-only nu
• out-only genereaza mesaje de eroare.
– Un mesaj cu eticheta Out in directia out. • Restul de sabloane pot
• robust-out-only genera erori. Orice mesaj,
– Un mesaj cu eticheta Out in directia out. exceptandul pe primul, poate
• out-in fi inlocuit cu un mesaj de
– Un mesaj cu eticheta Out in directia out. eroare in aceeasi directie.
– Un mesaj cu eticheta In in directia in
• out-optional-in
– Un mesaj cu eticheta Out in directia out.
– Optional un mesaj cu eticheta In in directia in
2015

Partea concreta a WSDL


• Contine:
– O multime de legaturi ce descriu modul cum sunt schimbate
mesajele in interactiunea din tre client si SW. O legatura
specifica formatul concret al mesajelor si detaliile
protocolului de transport al mesajelor, pentru fiecare
operatie si eroare a interfetei. O legatura se specifica cu
elementul binding.
– Specificatia locatiei unde este accesibil SW. Pentru un SW
se specifica interfata (unica !) furnizata si porturile (engl.
endpoint) unde poate fi accesat SW. Specificatia locatiei
serviciului se face cu elementul service.

2015
Schema de definire a legaturilor si serviciilor
<?xml version="1.0" encoding="utf-8" ?>
<description
. . .
xmlns:wsoap= "http://www.w3.org/ns/wsdl/soap"
xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
. . .
<binding name="reservationSOAPBinding"
interface="tns:reservationInterface"
. . . >
. . .
</binding>
<service name="reservationService"
interface="tns:reservationInterface">
. . .
</service>
</description>
• wsoap defineste spatiul de nume al extensiilor SOAP 1.2 pentru legaturi.
• soap defineste spatiul de nume in care sunt definite elementele ce compun
un “plic” al mesajelor SOAP. In exemplele SOAP a fost definit ca env.
2015

Definirea legaturilor
<binding name="reservationSOAPBinding"
interface="tns:reservationInterface"
type="http://www.w3.org/ns/wsdl/soap"
wsoap:protocol="http://www.w3.org/2003/05/soap/bindings/HTTP/">
<operation ref="tns:opCheckAvailability"
wsoap:mep="http://www.w3.org/2003/05/soap/mep/soap-response"/>
<fault ref="tns:invalidDataFault" wsoap:code="soap:Sender"/>
</binding>
• Se defineste o legatura reservationSOAPBinding.
• Atributul interface defineste interfata opCheckAvailability careia ii este
asociata legatura. Interfata este definita in spatiul de nume tns.
• Atributul type specifica tipul mesajelor. Aici este vorba de mesaje SOAP.
• Atributul protocol defineste protocolul de transport, in acest caz HTTP.
• Elementul operation specifica prin atributul ref operatia pentru care se
specifica legatura. Atributul mep specifica sablonul de interactiune SOAP
ce se va folosi pentru a implementa sablonul abstract in-out.
• Elementul fault refera prin ref eroarea pentru care se stabileste legatura.
2015
Definirea serviciilor
<service name="reservationService"
interface="tns:reservationInterface">
<endpoint name="reservationEndpoint"
binding="tns:reservationSOAPBinding"
address ="http://greath.example.com/2004/reservation"/>
</service>

• Elementul service defineste numele serviciului.


• Atributul interface defineste interfata abstracta a serviciului.
• Elementul endpoint defineste un port pentru serviciul respectiv.
• Unui port i se asociaza o legatura cu atributul binding si o
adresa fizica (URI) cu atributul address.

2015

Documentarea serviciilor
<?xml version="1.0" encoding="utf-8" ?>
<description
. . . >
<documentation>
. . .
Aici se introduce comentariul serviciului
. . .
</documentation>
. . .
</description>

• Se realizeaza prin introducerea unui comentariu in cadrul


elementului documentation.

2015
Schema WSDL 2.0

Conform http://www.w3.org/TR/wsdl20-primer/ 2015