Home > python > python: socket per programmatori di coccio

python: socket per programmatori di coccio

Essendo io stesso un programmatore di coccio,
ho cercato di mettere insieme un po’ di informazioni
trovate in rete riguardanti i sockets.
Ovviamente si trova tutto sulla doc ufficiale di python e
sulla libreria di riferimento.

Mi piacevano però alcuni esempi, che posterò qui come promemoria.

Alcune delle “cose importanti” da sapere sono che:
– Il socket rappresenta la forma più usata di comunicazione
tra processi (IPC)
– Nella maggiorparte dei casi un non-programmatore come me
utilizzerà sockets di tipo STREAM su indirizzi e protocolli INET.
– se il socket non verrà trattato come un file (con metodi read
e write), i metodi saranno send() e recv(), rispettivamente per
spedire e ricevere un messaggio.
– se recv() restituisce 0 byte, significa che è caduta la connessione
dall’altra parte

Ecco un esempio semplice per il “lato server”:

# myserver.py
import socket

port = 4000
host = ""
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((host, port))
server_socket.listen(5)

print "Type 'Q' or 'q' to QUIT"
print "Server Waiting for client on port ", port

while True:
    client_socket, address = server_socket.accept()
    print "Connection from ", address
    while True:
        server_data = raw_input("--> server: ")
        if server_data.lower() == 'q':
            client_socket.send(server_data)
            client_socket.close()
            break
        else:
            client_socket.send(server_data)
 
        client_data = client_socket.recv(1024)
        if client_data.lower() == 'q':
            print "Quit from client"
            client_socket.close()
            break
        else:
            print "<-- client: ", client_data
    break

In sostanza:
Scegliamo una porta di comunicazione.
Scegliamo l’host server che può essere, per esperimenti in
locale “”, “localhost”, “127.0.0.1”.

Creiamo l’oggetto socket

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

dove AF_INET rappresenta il protocollo TCP/IP con indirizzo ip IPv4
e SOCK_STREAM è il tipo di socket.
Leghiamo il socket, tramite bind() all’host e porta appena definiti:

server_socket.bind((host, port))

Nota:
Se volessimo rendere visibile il socket dall’esterno utilizzeremmo gethostname()

server_socket.bind((server_socket.gethostname(), port))

Mettiamo ora il socket (lato server) in ascolto:

server_socket.listen(5)

creando successivamente 2 cicli while annidati, con il primo accettiamo le
connessioni dal client e ne associamo socket ed indirizzo alle variabili
client_socket e address grazie ad accept():

while True:
    client_socket, address = server_socket.accept()
    ...

dopodichè, con il secondo ciclo annidato,

    while True:
        server_data = raw_input("--> server: ")
        if server_data.lower() == 'q':
            client_socket.send(server_data)
            client_socket.close()
            break
        else:
            client_socket.send(server_data)

creo il messaggio tramite raw_input().
Tramite if, nel caso venga digitato ‘q’, spedisco comunque
il messaggio per avere un riscontro lato-client, dopodichè
chiudo la connessione.
Allo stesso modo, se ho passato l’if precedente senza chiudere
la connessione, essendo in ascolto, nel caso il client abbia
spedito un messaggio, lo ricevo tramite recv() e lo associo alla
variabile client_data:

        client_data = client_socket.recv(1024)
        if client_data.lower() == 'q':
            print "Quit from client"
            client_socket.close()
            break
        else:
            print "<-- client: ", client_data

se (come vedremo dal codice client) dovesse essere arrivato un quit (‘q’),
chiudiamo il socket ed usciamo dal ciclo con un break.
Altrimenti stampo a video il messaggio.
In caso di quit dal client, il break ci farebbe uscire dal while annidato
e per uscire dal while principale, siccome non voglio che il socket
rimanga su, uso un altro break.

Ora analizziamo il lato client:

# myclient.py
import socket

port = 4000
host_server = "localhost"
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((host_server, port))

print "Type 'Q' or 'q' to QUIT"

while True:
    server_data = client_socket.recv(1024)
    if server_data.lower() == 'q':
        print "Quit from server"
        client_socket.close()
        break
    else:
        print "<-- server: ", server_data
        client_data = raw_input("--> client: ")
        if client_data.lower() != 'q':
            client_socket.send(client_data)
        else:
            client_socket.send(client_data)
            client_socket.close()
            break

Si definiscono porta (la stessa dove il socket_server
è in ascolto, ovvio) e address del socket server.
Si crea l’oggetto socket e lo si connette con il metodo
connect():

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((host_server, port))

Si crea il solito loop dove mettiamo il socket immediatamente
in ricezione tramite recv():

while True:
    server_data = client_socket.recv(1024)

Effettuo il test di controllo per verificare che il server_socket
non abbia chiuso la connessione.

    if server_data.lower() == 'q':
        print "Quit from server"
        client_socket.close()
        break
    else:
        print "<-- server: ", server_data

Se il lato server non ha effettuato il quit (else),
stampo a video il messaggio e, subito dopo, creo il
messaggio lato client da spedire al server:

        client_data = raw_input("--> client: ")

Nonostante il messaggio venga comunque spedito al lato
server, effettuo un test di controllo, per chiudere la
connessione nel caso venga digitato ‘q’.
Come visto precedentemente, tale messaggio viene spedito
ugualmente in modo che venga sottoposto a test di controllo
anche nel lato server.

Link utili:
Doc ufficiale di python
Socket Programming Howto
Libreria di riferimento di Python (socket)

materiale per programmatori di coccio:
decoratori
pattern observer
pattern mvc

Categorie:python Tag:
  1. giugno 3, 2012 alle 6:45 pm

    Grazie tante, mi mancavano i socket🙂

  1. giugno 17, 2013 alle 11:27 am

Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

%d blogger cliccano Mi Piace per questo: