CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS
CAMPUS VII - UNIDADE TIMÓTEO - Engenharia de Computação
Sistemas Distribuídos
Lucas Pantuza Amorim
Trabalho Prático 2:
RPC/RMI
Diêgo Gomes Piovezana, Habacuque Boy Barbosa Neves
1 Introdução
Neste relatório estão descritos os procedimentos realizados para execução do 2º trabalho prático da
disciplina de Sistemas Distribuídos do curso de Engenharia de Computação do CEFET-MG, campus Ti-
móteo. Tal feito utiliza como base o trabalho anterior, ou seja, foi implementado um par de programas
operando no modelo ponto-a-ponto e utilizado chamadas remotas de procedimento utilizando a lin-
guagem de programação Python. Porém, em especial a esta atividade, em divergência com o trabalho
base, não foi feito uso de soquete como método de comunicação, mas sim, utilizado a tecnologia de
Chamada de Procedimento Remoto (RPC) [1], mais precisamente foi utilizado a biblioteca nativa da
linguagem, intitulada ’xmlrpc’.
2 Metodologia
Utilizando o ambiente Linux com Python 3.9.1 devidamente instalado e configurado e novamente fa-
zendo uso da biblioteca ’tkinter’ instalada utilizando o comando ’pip’, foi criado um módulo chamado
’[Link]’ que utiliza a biblioteca nativa ’xmlrpc’ do Python. Para tal feito, foi utilizado a documenta-
ção oficial [2].
O módulo exporta uma função para ’escutar’ mensagens que cria em um servidor (server) que imple-
menta o protocolo ’xmlrpc’ no processo, na qual expõe remotamente uma função ’onMessage’ passada
como argumento. Também é exportada uma função que retorna outra função para enviar mensagens
para um server remoto, criando um cliente ’xmlrpc’ que se comunica chamando a função ’onMessage’
do server remoto. Uma característica especial da função de escutar mensagens RPC é que ela executa
um server em ’looping’. Logo, foi transferida para outra thread, para não bloquear o programa.
Sistemas Distribuídos
Lucas Pantuza Amorim
Por fim, também foi criado um módulo para desenhar as telas do programa utilizando a biblioteca ’tkin-
ter’ (Código 2). Este módulo desenha uma tela de login onde é possível inserir o endereço do server RPC
remoto e uma tela de chat onde ocorre a comunicação de fato. As telas chamam as funções relevantes
do módulo de RPC citado anteriormente.
Ao criar a tela de chat o programa assume que o server remoto (IP passado na tela de login) está escu-
tando na porta 8000. Em seguida tenta enviar uma mensagem com o conteúdo ’ack’ (veja a figura 6).
Caso o envio falhe o programa iniciará um server ’xmlrpc’ na porta 8000 e assumirá que o outro está na
porta 8001. Caso o envio seja bem sucedido o programa criará um server na porta 8001 e continuará
assumindo que o server remoto está na porta 8000.
3 Resultados
As mensagens conseguiram ser trocadas normalmente entre dois softwares. Contudo, ao abrir uma
quantidade superior de programas, um erro (provido do server ao tentar escutar mensagens numa porta
ocupada) informando que o endereço já está sendo utilizado será imprimido no console para cada
novo programa aberto (veja a figura 8). Todavia, eles continuarão abertos sendo até capazes de enviar
mensagens (para o server na porta 8000), mas não são capazes de receber.
3.1 Comando para iniciar o sistema
Figura 1: Comando para iniciar o sistema
Sistemas Distribuídos
Lucas Pantuza Amorim
3.2 Tela de login
Figura 2: Tela de login do sistema
3.3 Tela do chat
Figura 3: Tela do chat
Sistemas Distribuídos
Lucas Pantuza Amorim
3.4 Comunicação cliente/servidor
Figura 4: Chat cliente/servidor
3.5 Mensagem ’ack’
Figura 5: Primeira mensagem ’ack’ enviada ao destinatário
Sistemas Distribuídos
Lucas Pantuza Amorim
3.6 Comportamento sem e com destinatário
Figura 6: Comportamento quando um destinatário (outro/cliente 2) entra no chat
3.7 Erros
3.7.1 Ausência de destinatário
Figura 7: Erro para quando não há ninguém para receber uma mensagem
Sistemas Distribuídos
Lucas Pantuza Amorim
3.7.2 Endereço em uso
Figura 8: Erro quando o endereço já está sendo utilizado
4 Análise
O programa em RPC foi muito mais resiliente e fácil de implementar se comparado ao software utili-
zando soquetes. Tal comportamento talvez se deve ao fato de utilizar uma abstração de mais alto nível
com mais uma camada de robustez adicionada pelo protocolo ’xmlrpc’ ao invés de TCP puro.
5 Conclusão
Com a realização deste trabalho prático, instigou-se uma compreensão prática do conceitos teóricos
abordados na disciplina de Sistemas Distribuídos, de modo especial, ao que se refere à comunicação
entre processos, fazendo uso de chamadas de procedimento remoto (RPC), sendo portanto outro me-
canismo (com algumas vantagens) para realizar a comunicação entre processos, além da alternativa
abordada no trabalho anterior da disciplina, na qual foi base para realizada deste.
6 Código Fonte da Aplicação
Sistemas Distribuídos
Lucas Pantuza Amorim
6.1 Main
1 import g u i U t i l s
2
3 d e f main ( ) :
4 # desenha a t e l a
5 gui = guiUtils . create ()
6
7 main ( )
codigo/[Link]
6.2 Interface Gráfica
1 # b i b l i o t e c a de i n t e r f a c e g r a f i c a p a r a p y t h o n
2 import t k i n t e r as tk
3 import t k i n t e r . s c r o l l e d t e x t
4
5 # b i b l i o t e c a n a t i v a de t h r e a d s do p y t h o n
6 import threading
7
8 # n o s s a b i b l i o t e c a de r p c
9 import r p c U t i l s
10
11 # c r i a uma j a n e l a de f u n d o c o l o r i d o em t e l a c h e i a
12 d e f window ( ) :
13 window = t k . Tk ( )
14 w i n d o w . o p t i o n _ a d d ( ’ * F o n t ’ , ’ 30 ’ )
15 w i n d o w . a t t r i b u t e s ( ’ − zoomed ’ , T r u e )
16 window . c o n f i g u r e ( b a c k g r o u n d = ’# e 5 f 2 f c ’ )
17 window . t i t l e ( " c h a t " )
18 r e t u r n window
19
20
21 # c r i a a t e l a de c h a t s
22 def chatScreen ( host ) :
23
24 # a s s u m i m o s que e x i s t e um s e r v e r r p c e s c u t a n d o n a p o r t a 8000
25 send = r p c U t i l s . s e n d C r e a t e ( host ,8000)
26 # a s s u m i m o s que s e r v e r s a b e que n o s s o s e r v e r l o c a l e s t a na p o r t a 8001
27 s e l f P o r t = 8001
28
29 # t e n t a m a n d a r uma mensagem g e n e r i c a
30 try :
31 send ( ’ ack ’ )
Sistemas Distribuídos
Lucas Pantuza Amorim
32 except :
33 # e n v i o da mensagem f a l h o u
34 # l o g o o s e r v e r n a o e s t a v a n a p o r t a 8000
35 # a s s u m i m o s que e l e e s t a n a 8001
36 send = r p c U t i l s . sendCreate ( host ,8001)
37 # e que o s e r v e r r e m o t o v a i a s s u m i r que e s t a m o s na 8000
38 s e l f P o r t = 8000
39
40
41 # v a r i a v e l que g u a r d a mensagem s e n d o e s c r i t a
42 msg = t k . S t r i n g V a r ( )
43
44 # e q u i v a l e n t e a um ’ d i v ’ no h t m l
45 f r a m e = t k . F r a m e ( bg = " w h i t e " )
46 e n t r y F r a m e = t k . F r a m e ( f r a m e , bg = " w h i t e " )
47
48 # um t e x t o q u a l q u e r
49 t i t l e = t k . L a b e l ( f r a m e , t e x t = " C h a t " , f g = " b l a c k " , bg = " w h i t e " , f o n t = ( " a r i a l "
,25) )
50
51 # uma a r e a de t e x t o com r o l a g e m n a o e d i t a v e l
52 # para mostrarmos mensagens r e c e b i d a s
53 t e x t = t k . s c r o l l e d t e x t . S c r o l l e d T e x t ( f r a m e , w r a p = t k . WORD , f g = " b l a c k " , bg = "
white " )
54 t e x t . v b a r . c o n f i g ( bg = " w h i t e " )
55 t e x t . c o n f i g ( s t a t e = t k . DISABLED )
56
57 # um i n p u t de t e x t o
58 e n t r y = t k . E n t r y ( e n t r y F r a m e , f g = " b l a c k " , bg = " w h i t e " , w i d t h = 5 0 ,
t e x t v a r i a b l e = msg )
59
60 # d e i x a a c a i x a de t e x t o e d i t a v e l
61 # a d i c i o n a uma mensagem n e l a
62 # d e s a t i v a a e d i c a o l o g o em s e g u i t a
63 # t y p e i n d i c a i n f o r m a c o e s s o b r e quem mandou a mensagem
64 d e f a p p e n d M s g ( msg , t y p e ) :
65 t e x t . c o n f i g ( s t a t e = t k . NORMAL )
66 t e x t . i n s e r t ( t k . INSERT , t y p e + " : " + msg + " \ n " )
67 t e x t . c o n f i g ( s t a t e = t k . DISABLED )
68
69 # c r i a um s e r v e r r p c p a r a que p e r m i t i r a c h a m a r a f u n c a o ’ a p p e n d M s g ’
remotamente
70 # com uma mensagem de a r g u m e n t o
71 def l i s t e n M s g ( ) :
72 r p c U t i l s . l i s t e n ( s e l f P o r t , l a m b d a msg : a p p e n d M s g ( msg , " o u t r o "
) )
73
74 # chama uma f u n c a o r e m o t a com uma mensagem que e s c r e v e m o s
Sistemas Distribuídos
Lucas Pantuza Amorim
75 def sendMsg ( ) :
76 # i g n o r a m e n s a g e n s v a z i a s ou m a i o r e s que 1 0 2 4 b y t e s
77 i f ( msg . g e t ( ) a n d l e n ( msg . g e t ( ) ) < = 1 0 2 4 ) :
78 try :
79 # chama a r p c de r e c e b e r m e n s a g e n s
80 # mandando p a r a o s e r v e r a mensagem que e s t a v a m o s
escrevendo
81 s e n d ( msg . g e t ( ) )
82 # s a l v a n o s s a p r o p i a mensagem n a l i s t a v i s i v e l de
mensagens
83 a p p e n d M s g ( msg . g e t ( ) , " eu " )
84 except :
85 # e n v i o da mensagem f a l h o u
86 # i n d i q u e na t e l a a f a l h a
87 appendMsg ( ’ n o h n i n g u m p a r a r e c e b e r s u a mensagem ’ ,
" erro " )
88 # l i m p a o campo de e s c r i t a de mensagem
89 msg . s e t ( ’ ’ )
90
91
92 # b o t a o de e n v i o de mensagem
93 b u t t o n = t k . B u t t o n ( e n t r y F r a m e , t e x t = " E n v i a r " , f g = " b l a c k " , bg = " w h i t e " ,
command = s e n d M s g )
94
95 # p o s i c i o n a e l e m e n t o s na t e l a
96
97 e n t r y . g r i d ( column =0 , row =0 , padx = 1 0 )
98 b u t t o n . g r i d ( column = 1 , row =0 , padx = 1 0 , pady = 1 0 )
99
100 t i t l e . pack ( padx = 1 0 )
101 t e x t . pack ( expand = 1 , f i l l = tk . Y )
102 entryFrame . pack ( )
103
104 frame . pack ( expand = 1 , f i l l = tk . Y )
105
106 # como o s e r v e r r p c eh um l o o p i n f i n i t o
107 # ele t r a v a r i a o programa
108 # logo jogamos ele para outra thread
109 thread = t h r e a d i n g . Thread ( t a r g e t = l i s t e n M s g )
110 thread . s t a r t ( )
111
112
113 # g e r a uma t e l a de l o g i n
114 # o n d e i n f o r m a m o s o i p de quem v a i r e c e b e r n o s s a s m e n s a g e n s
115 def l o g i n S c r e e n ( ) :
116
117 # div
118 f r a m e = t k . F r a m e ( bg = " w h i t e " )
Sistemas Distribuídos
Lucas Pantuza Amorim
119 # input
120 e n t r y F r a m e = t k . F r a m e ( f r a m e , bg = " w h i t e " )
121
122 # v a r i a v e l que g u a r d a o i p
123 remoteHost = tk . S t r i n g V a r ( )
124 remoteHost . set ( ’ 1 2 7 . 0 . 0 . 1 ’ )
125
126 # texto qualquer
127 t i t l e = t k . L a b e l ( f r a m e , t e x t = " I n s i r a o e n d e r e o da o u t r a p e s s o a " , f g = "
b l a c k " , bg = " w h i t e " , f o n t = ( " a r i a l " , 2 5 ) )
128
129 # i n p u t o n d e o i p eh i n s e r i d o
130 e n t r y = tk . E n t r y ( entryFrame , t e x t v a r i a b l e = remoteHost , j u s t i f y = " c e n t e r " ,
f g = " b l a c k " , bg = " w h i t e " )
131
132 # d e s t r o i a t e l a a t u a l e v a i p a r a a t e l a de c h a t s
133 # passando o host i n s e r i d o
134 def goToChatScreen ( ) :
135 frame . d e s t r o y ( )
136 chatScreen ( remoteHost . get ( ) )
137
138 # b o t a o de mudar de t e l a
139 b u t t o n = t k . B u t t o n ( f r a m e , t e x t = " E n v i a r " , f g = " b l a c k " , bg = " w h i t e " , command =
goToChatScreen )
140
141 # c o l o c a os e l e m e n t o s na t e l a
142
143 t i t l e . pack ( pady =30 , padx = 1 0 )
144
145 entryFrame . pack ( )
146 e n t r y . g r i d ( column =0 , row =0 , padx = 1 0 )
147
148 b u t t o n . pack ( pady =20)
149
150 frame . pl ace ( r e l x =0.5 , r e l y =0.5 , anchor = ’ c e n t e r ’ )
151
152 r e t u r n frame
153
154
155
156
157 def crea te ( ) :
158
159 w = window ( )
160
161 # q u a n d o o c o r r e r um e r r o
162 # d e s t r u a o j a n e l a e m o s t r e e l e no c o n s o l e
163 def s h o w E r r o r ( s e l f , exc , val , tb ) :
Sistemas Distribuídos
Lucas Pantuza Amorim
164 w. destroy ()
165 print ( val )
166 t k . Tk . r e p o r t _ c a l l b a c k _ e x c e p t i o n = s h o w E r r o r
167
168 # cria tela delogin
169 ls = loginScreen ()
170
171 # desenha t e l a para sempre
172 w . mainloop ( )
codigo/[Link]
6.3 RPC
1 # b i b l i o t e c a n a t i v a do p y t h o n p a r a r p c
2 import xmlrpc . server
3 import xmlrpc . c l i e n t
4
5 # c r i a um s e r v e r do p r o t o c o l o x m l r p c
6 # com uma f u n c a o p a r a r e c e b e r m e n s a g e n s
7 def l i s t e n ( s e l f P o r t , onMessage ) :
8 # c r i a o s e r v e r e p e e p a r a e l e e s c u t a r numa d e t e r m i n a d a p o r t a
9 # o a l l o w _ n o n e , p e r m i t e n o s s a s f u n c o e s r p c nao r e t o r n a r e m v a l o r e s
10 s e r v e r = xmlrpc . s e r v e r . SimpleXMLRPCServer ( ( ’ l o c a l h o s t ’ , s e l f P o r t ) ,
allow_none = True )
11 # r e g i s t r a uma f u n c a o c h a m a d a ’ o n M e s s a g e ’ que eh a mesma que ’
o n M e s s a g e ’ r e c e b i d a como a r g u m e n t o
12 s e r v e r . r e g i s t e r _ f u n c t i o n ( onMessage , ’ onMessage ’ )
13 # c o l o c a o s e r v e r p a r a e x e c u t a r em l o o p
14 server . serve_forever ()
15
16 # c r i a um c l i e n t e do p r o t o c o l o x m l r p c
17 # e c r i a uma f u n c a o que u s a o c l i e n t e p a r a c h a m a r a f u n c a o r e m o t a ’
onMessage ’
18 # do s e r v e r que c o n e c t a m o s
19 def sendCreate ( remoteHost , remotePort ) :
20 # cria o cliente
21 remoteServer = xmlrpc . c l i e n t . ServerProxy ( f " http : / / { remoteHost } : {
remotePort } " , allow_none = True )
22 # chama a f u n c a o r e m o t a ’ o n M e s s a g e ’ , eh o e q u i v a l e n t e de e n v i a r m o s
uma mensagem p a r a o s e r v i d o r
23 r e t u r n remoteServer . onMessage
codigo/[Link]
Sistemas Distribuídos
Lucas Pantuza Amorim
Referências
[1] DEINFO. RPC - O que é. URL [Link] alunoso/2017/RPC/.
[2] Python Software Foundation. [Link] — Basic XML-RPC servers, 2021. URL
[Link]