Socket UNIX invés de TCP/IP

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:

uds.py

# -*- 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:

Arquivo descritor
Arquivo descritor

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.

cli.py

# -*- 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”:

Unix Domain Socket
Unix Domain Socket

Simples, hum?

Inscreva-se no nosso newsletter, alí em cima à direita e receba novos posts por email.

Siga-nos no Do bit Ao Byte no Facebook.

Prefere twitter? @DobitAoByte.

Inscreva-se no nosso canal Do bit Ao Byte Brasil no YouTube.

Nossos grupos:

Arduino BR – https://www.facebook.com/groups/microcontroladorarduinobr/
Raspberry Pi BR – https://www.facebook.com/groups/raspberrybr/
Orange Pi BR – https://www.facebook.com/groups/OrangePiBR/
Odroid BR – https://www.facebook.com/groups/odroidBR/
Sistemas Embarcados BR – https://www.facebook.com/groups/SistemasEmbarcadosBR/
MIPS BR – https://www.facebook.com/groups/MIPSBR/
Do Bit ao Byte – https://www.facebook.com/groups/dobitaobyte/

Próximo post a caminho!

Djames Suhanko

Djames Suhanko é Perito Forense Digital. Já atuou com deployer em sistemas de missão critica em diversos países pelo mundão. Programador Shell, Python, C, C++ e Qt, tendo contato com embarcados ( ora profissionalmente, ora por lazer ) desde 2009.

Deixe uma resposta