Comunicazione TCP in python

Visto che fra i miei futuri progetti c’è la costruzione di un robot, sto iniziando a prepararmi anche dal punto di vista di programmazione. Il robot dovrà essere necessariamente controllabile a distanza e la forma più efficace mi è sembrata quella di utilizzare il wifi.

Semplice ed ecomico, disponibile su tutte le piattaforme e supportato dai linguaggi il WIFI, in particolare con il protocollo tcp-ip è sicuramente la soluzione migliore. Visto che probabilmente utilizzerò il python come linguaggio di programmazione ho pensato di fare alcune prove per portarmi avanti con gli esperimenti.

Recuperare la homepage di un sito web

Come prima cosa ho pensato di fare un sorgente minimale che interroga un qualsiasi sito web chiedendogli la homepage. Non certo un programma per navigare, anche perchè riceve solo html che il programma visualizza in un brutale formato testo. Questo il codice

import socket
print('inizio programma')
s=socket.socket()
s.connect(("virgilio.it",80))
s.sendall(b"GET / \r\n ")
dati = s.recv(10000)
print(dati)
print('fine programma')

Come sempre import serve ad importare le librerie che andremo ad utilizzare, il print iniziale e finale serve per seguire l’andamento del programma. la variabile s conterrà l’oggetto socket che ci serve per stabilire una connessione. Utilizzando la funzione connect e passandogli come parametri il nome del sito e la porta da utilizzare (per la navigazione web la porta di default è 80) attiviamo la connessione e con il comando sendall inviamo dei comandi al server remoto. In questo caso il comando è “GET /” che richiede la homepage (potrebbe essere index.html o index.php o qualsiasi altra pagina il server abbia come home).

Con la funzione recv impostiamo nella variabile dati i dati ricevuti e li stampiamo per vederne il risultato, incomprensibile a chi non conosce html.

un semplice server tcp in python

Ora vediamo come far comunicare fra loro due programmi. Uno dei due deve comportarsi come server e l’altro come client, cioè uno deve restare in ascolto e attendere l’altro (il client) che abbia qualcosa da dire, a quel punto si stabilisce la connessione e entrambi possono trasmettere e ricevere. Vediamo prima il blocco di istruzioni da mettere nel server:

import socket

print ('avvio server');
HOST = '127.0.0.1' 
PORT = 60001
s = socket.socket() #senza parametri protocollo tcp-ip
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()

print('Connesso ad IP: ', addr)
while True:
    dati = conn.recv(1024)
    if not dati:
        break
    conn.sendall(b'restituisco dati ricevuti:'+dati)
    print('dati ricevuti: ',dati)
s.close()    
print('Fine programma')

Nella variabile Host impostiamo l’IP del network che vogliamo utilizzare (il nostro IP se abbiamo un unica scheda di comunicazione) nell’esempio ho utilizzato l’indirizzo di loopback che indica il computer corrente. Nella variabile host ho impostato il numero della porta, ricordatevi che le prime 1024 sono riservate. Nella variabile s viene creato l’oggetto socket che chiamato senza paramentri prevede il protocollo tcp e ipv4.

Il comando bind crea la connessione sull’host e sulla prota specificati e il comdando listen mette il programma in ascolto, cioè in attesa di qualche client che si connetta. Quando avviene la connessione tramite il comando accept impostato i dati della connessione nella variabile dati e l’indirizzo del server nella variabile addr e visualizziamo l’avvenuta connessione e il relativo indirizzo.

Con un ciclo infinito, restituiamo al client i dati ricevuti dopo avergli anteposto una stringa per distinguerli nelle prove e visualizziamo i dati ricevuto, fintanto che riceviamo dati. Finito di ricevere dati chiudiamo la connessione e fine.

Da notare che il programma rimane fermo in attesa di una connessione e appena la connessione è avvenuta e visualizzata va in fine. Questo ha come conseguenza che non è utilizzabile così com’è all’interno di un programma che fa altre cose e inoltre non può effettuare più di una connessione per volta. Vedremo in un prossimo articolo come superare queste limitazioni.

Un semplice client TCP in python

import socket

HOST = '127.0.0.1'  
PORT = 60001        
s = socket.socket()
s.connect((HOST, PORT))
s.sendall(b'Testo di prova, andate su salentoplus.it')
dati = s.recv(1024)
print('Dati ricevuti', repr(dati))
s.close()

Il programma cliente è molto più semplice del server dopo aver creato l’oggetto socket si connette al loopback (o a qualsiasi altro host) utilizzando la porta specificata nella variabile port e invia i dati usando la funzione sendall. L b che precede la stringa che stiamo inviado è un costruttore python che serve a convertirla in una sequenza di byte, il tipo di dato che si aspetta la funzione sendall.

Subito dopo aver inviato il nostro messaggio il programma si mette in attesa della risposta utilizzando la funzione recv e la carica nella variabile dati che subito dopo viene visualizzata.

Per fare una prova dei due programmi su un personal computer potete far partire il server da una riga di comando entrando nella cartella che contiene il sorgente e digitando il comando python sorgente.py (al posto di sorgente mette il nome con cui lo avete salvato). il programma visualizzerà il messaggio “avvio server” e resterà in attesa. Se non sapete come si accede alla riga di comando la via più semplice è quella di cliccare su start e digitare cmd, il sistema vi suggerirà il prompt dei comandi. Per entrare nella cartella contentente il sorgente dovete utilizzare il comando cd (change directory) seguito dal nome della cartella, se dovete risalire di una cartella utilizzate il comando cd .. se volete vedere i file nella cartelal in cui vi trovare usate il comando dir.

Ora potete fare partire il client utilizzando l’ambiente di programmazione di python o un’altra finestra di comando. Vedrete che si visualizza il il testo che avete inviato precedeuto da un testo aggiunto dal server e se andate sulla finestra che contiene il server vedrete le informazioni di connessione e i dati ricevuti dal client.

Per oggi finiamo qui, in un prossimo articolo aggiungerò il controllo degli errori, la possibilità di avere più connessioni contemporanemante e soprattuto il programma server non resterà bloccato in attesa di un client ma continuerà a svolgere altre attività.

Maurizio

Lascia un commento