02. Python: client-server

I programmi inseriti in questa pagina utilizzano il paradigma client-server e vanno eseguiti contestualmente.

Senza alcuna modifica possono essere eseguiti sullo stesso computer (dopo aver disabilitato momentaneamente il firewall locale per consentire la comunicazione via TCP/IP) oppure su computer differenti avendo l'accortezza di modificare l'indirizzo del server associato alla variabile HOST nel programma client.

In ambinte Windows è possibile monitorare lo stato della connessione tramite il comando netstat -an.


Programma server

Accetta le connessioni su tutte le interfacce compreso localhost.

Acquisisce un messaggio dal client e invia lo stesso messaggio in maiuscolo.

Opera con un solo client alla volta e termina quando un client invia il messaggio "FINE".

  • Codice sorgente


# echo-server.py


import socket


HOST = "" # 127.0.0.1 è localhost

PORT = 65400 # Porta su cui il server si pone in listen (da 1024 a 65535)


try:

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

except Exception as e:

print("la creazione del socket è fallita, sto uscendo...", e)

exit(1)


print("socket creato")


try:

s.bind((HOST, PORT))

except Exception as e:

print("binding fallito:", e)

exit(1)


print("binding del socket con", (HOST, PORT), "avvenuto con successo")


try:

s.listen()

except Exception as e:

print("operazione di listen fallita:", e)

exit(1)


while True:

try:

print("in attesa del client...")

conn, addr = s.accept()

print("connesso con il client", addr)

except Exception as e:

print("connessione fallita:", e)

exit(1)


while True:

try:

blocco = conn.recv(1024)

if not blocco:

conn.close()

print("il client", addr, "ha chiuso la connessione")

break

testo = blocco.decode("ascii")

print("ricevuto dal client il messaggio:", testo)

conn.sendall(bytes(testo.upper(), "ascii"))

except Exception as e:

conn.close()

print("connessione chiusa forzatamante dal client", addr)

break

if testo == "FINE":

break;


s.close()

print("chiusura del socket e terminazione del server")

  • Esecuzione:

socket creato

binding del socket con ('', 65400) avvenuto con successo

in attesa del client...

connesso con il client ('127.0.0.1', 54366)

ricevuto dal client il messaggio: messaggio dal client n. 1

il client ('127.0.0.1', 54366) ha chiuso la connessione

in attesa del client...

connesso con il client ('127.0.0.1', 54372)

ricevuto dal client il messaggio: messaggio dal client n. 2

il client ('127.0.0.1', 54372) ha chiuso la connessione

in attesa del client...

connesso con il client ('127.0.0.1', 54388)

ricevuto dal client il messaggio: FINE

il client ('127.0.0.1', 54388) ha chiuso la connessione

chiusura del socket e terminazione del server


Programma client

Effettua la connessioni ad un server eseguito sulla stesso computer tramite l'indirizzo localhost corrispondente a 127.0.0.1.

Chiede all'utente di inserire un messaggio di testo.

Invia il messaggio al server ed attende la risposta che stampa a video.

In corrispondenza del messaggio "FINE" il server termina.

  • Codice sorgente


# echo-client.py


import socket


HOST = "127.0.0.1" # Inserire l'indirizzo IP del server

PORT = 65400 # Inserire il port del server


try:

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

except Exception as e:

print("la creazione del socket è fallita, sto uscendo...", e)

exit(1)


print('socket creato')


try:

client.connect((HOST,PORT))

except Exception as e:

print('connessione fallita:', e)

exit(1)


print('connessione effettuata')


msg = input("inserisci un messaggio: ")


try:

client.sendall(bytes(msg,"ascii"))

except Exception as e:

print('operazione di send fallita:', e)

exit(1)


try:

blocco = client.recv(1024)

except Exception as e:

print('operazione di recv fallita:', e)

exit(1)


testo = blocco.decode("ascii")

print("risposta ricevuta dal server:", testo)

client.close()


  • Esecuzione n. 1:

socket creato

connessione effettuata

inserisci un messaggio: messaggio dal client n. 1

risposta ricevuta dal server: MESSAGGIO DAL CLIENT N. 1

  • Esecuzione n. 2:

socket creato

connessione effettuata

inserisci un messaggio: messaggio dal client n. 2

risposta ricevuta dal server: MESSAGGIO DAL CLIENT N. 2

  • Esecuzione n. 3:

socket creato

connessione effettuata

inserisci un messaggio: FINE

risposta ricevuta dal server: FINE

Il seguente schema illustra come avviene l'interazione tra client e server quando si usa il protocollo TCP.

L'elemento centrale è il socket che è l'oggetto attraverso il quale è possibile la connessione e che consente lo scambio dei dati.

Lato server compaiono due socket: il primo è permanente (resta cioè in vita per tutta la durata del programma) ed è raggiunto dal client al momento della connessione. Durante questa fase viene però generato un nuovo socket lato server (socket temporaneo) sul quale si innesta effettivamente la connessione del client.