[Python] I Socket: un client TCP-IP
Tue 18 June 2013Ho trovato alcune guide molto interessanti per la programmazione dei socket in Python, ed ho deciso di cominciare a studiare un po il linguaggio.
Quale situazione migliore se non quella di commentare gli esercizi per fissare il tutto e, per chi fosse interessato, insegnare qualcosa.
Premetto che il codice e la procedure è tutto tranne farina del mio sacco:
Quest blog ha ottimi articoli sul Networking e, ovviamente, su Python :)
In particolare ho utilizzato una Guida introduttiva ai Sockets in Python; fate tesoro del sito, perché è davvero ottimo.
Per aiutarmi ed aiutarvi, metto anche il link alle pagine di manuale sui sockets (è python 2.7).
L'articolo sul blog del link è composto di due parti:
-
la costruzione di un client python che si connette ad un server, invia dati sul socket e attende la risposta prima di chiudere la comunicazione;
-
la creazione di un server, sempre in python, che si mette in ascolto su una porta e fa da "pappagallo" stampando a schermo quello che ricevere dal mittente, anche in multi-threading.
Oggi io descriverò il client, lasciano il server python per la prossima..
Il client
Ed ecco il mio primo socket:
1 2 3 4 5 6 7 8 9 10 |
|
La mia intestazione deriva dal fatto che utilizzando Archlinux ho Python3 come interprete di _default _mentre questo codice è stato creato per python 2.x. La maggior parte delle distribuzioni utilizzano python 2.x quindi dovreste poter utilizzare
1 |
|
Senza stare troppo a divagare, in queste quattro righe di codice si importano le librerie standard pyhton per i sockets (import socket) e di quelle di sistema (guarda un po) per la gestione dell'I/O, l'imput utente etcetc..
Visto che, chi ha fatto la guida è una persona colta, lui ha utilizzato un metodo di gestione delle "eccezioni" del tipo: prova a fare questo e se non riesci, giustificati con questo.
La forma è try:/except: e come tutte le cose in python gli spazi e l'indentazione contano.
Quel che si "prova" (try) a fare è creare un socket, associando la variabile sockMe:
socket.AF_INET, socket.SOCK_STREAM
Dove AF_INET sta per protocollo IP e SOCK_STREAM è il portocollo tcp (indovinate cosa è SOCK_DATAGRAM..).
Andando avanti col codice, aggiungiamo un po di pezzi dato che un socket da solo non fa la felicità..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
Facciamo faville :)
Ora stiamo usando il socket, connettendoci ad un host ed una _porta _che definiamo con _argv (_cioè dall'input passando due argomenti allo script tipo "./client.py google.com 80").
socket.gethostbyname, invece, è il resolver python, che cerca di risolvere l'hostname tramite dns o file /etc/hosts; anche questa volta proviamo a risolvere e, se tutto fila liscio, eseguiamo un sockMe.connect per aprire la connessione con l'host (risolto come IP) e la porta definiti.
Ora che abbiamo un bel socket aperto e connesso all'altro capo della linea, perché non inviamo un bel messaggio al nostro interlocutore:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
|
Semplicemente, con un altro metodo try/except inviamo il messaggio salvato nel buffer con il comando _sendall. _Questo comando svuota il buffer inviando tutto quello che trova all'altro capo della connessione.
Ed ora, il tocco finale: riceviamo la risposta, la leggiamo, la stampiamo e in fine chiudiamo la comunicazione da bravi sviluppatori (non vogliamo lasciare appese le sessioni giusto?!).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
|
recv è impostato per ricevere una certa quantità di dati (nel nostro caso 1024 byte). Per concludere in bellezza lo script, la sessione e l'articolo, chiudiamo il nostro socket python invocando la funzione close().