Manual
do
Maker
.
com
Para muitos, falar de domain socket unix é algo manjado, mas tão manjado que é como falar de mouse USB. Mas outros tantos não conhecem e é um recurso extremamente útil do sistema para fazer IPC (Inter-Process Communication). Esse recurso é muito utilizado e bastante útil tanto para sistemas grandes e complexos como para sistemas minimalistas rodando em embedded e por isso resolvi fazer o exemplo em cima do Raspberry, que roda um Linux tradicional tanto quanto roda Linux em uma arquitetura X86.
No primeiro momento pode ser difícil para você imaginar uma aplicação legítima para IPC, afinal é comum resolver tudo dentro de um mesmo programa, ou ainda, utilizar named pipe para esse propósito. Mas vamos a um exemplo bobo; um programa cria um arquivo com data/hora dentro, então repassa o nome do arquivo para o segundo processo, que lerá, exibirá na tela e então apagará o arquivo original. O server fica assim:
# -*- coding: utf-8 -*-
#!/usr/bin/env python
import socket
import sys
import datetime
import os
tsLen = 10
#definicao do UDS
server_address = './uds_socket'
# Garanta primeiramente que o socket ja nao existe
try:
os.unlink(server_address)
except OSError:
if os.path.exists(server_address):
raise
#Nesse ponto, sabe-se que nao existe o UDS. Cria-se:
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind(server_address)
#inicia a escuta
sock.listen(1)
#mantem-se interativo aa conexao
while True:
connection, client_address = sock.accept()
try:
print >>sys.stderr, 'Origem:', client_address
while True:
data = connection.recv(tsLen)
print >>sys.stderr,'Recebido: "%s"' % data
if data:
print >>sys.stderr,'Lendo conteudo...'
filename = str(data)+".txt"
if os.path.isfile(filename):
f = open(filename,'r')
print >>sys.stderr, 'conteudo: ',f.readline()
f.close()
print >>sys.stderr,str(datetime.datetime.fromtimestamp(long(str(data))))
else:
print >>sys.stderr, 'Fim de processo', client_address
break
finally:
connection.close()
Não confunda isso com gambiarra, porque não é. Apesar de estar sobre o sistema de arquivos, uds_socket (o nome dado a ele nesse programa, mas pode ser qualquer outro) é um arquivo descritor, executa-se em memória e não gera I/O em disco:
Um arquivo descritor aponta para um dispositivo, não é um arquivo comum no disco. Por exemplo, em /dev estão os dispositivos do sistema, como disco rígido, mouse, teclado, etc. Os dispositivos de armazenamento são chamados "dispositivos de bloco" e dispositivos como teclado e mouse são chamados "dispositivos de caractere". No caso do socket, ele é identificado pelo 's' de socket, como pode ser visto com o comando 'ls -l'. O tipo do arquivo pode ser visto com 'file uds_socket'. Tendo deixado isso claro, podemos partir para o client.
# -*- coding: utf-8 -*-
#!/usr/bin/env python
import socket
import sys
import time
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
server_address = './uds_socket'
print >>sys.stderr, 'Conectando em %s' % server_address
try:
sock.connect(server_address)
except:
print >>sys.stderr, msg
sys.exit(1)
try:
ts = str(long(time.time()))
f = open(ts+".txt","w")
f.write(sys.argv[1]+"\n")
f.close()
sock.sendall(ts)
finally:
print >>sys.stderr, 'Fechando conexao'
sock.close()
Rode o server, então rode o cliente passando qualquer informação como parâmetro. Eu passei um "hello":
Simples, hum?
Inscreva-se no nosso canal Manual do Maker no YouTube.
Também estamos no Instagram.
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.