Una semplice architettura client-server TCP/IP in Python

Una serie di workshop applicativi sull'uso di Python?

Con questo workshop viene presentato un semplice modulo, sviluppato all'IFAC, per realizzare applicazioni client-server in Python con protocollo proprietario e ne vengono illustrate alcune applicazioni esemplificative.

Sarebbe interessante se questo fosse il primo di una serie di semplici workshop applicativi in cui vengono illustrate applicazioni in Python sviluppate internamente, che possono essere di utilità generale, o per un riutilizzo diretto oppure come spunto di riflessione per approfondire alcuni aspetti del linguaggio. Tra gli argomenti che vengono in mente in proposito: accesso ai database, gestione avanzata di immagini e colori, gestione della strumentazione e rapporti con l'hardware.

Impostazione

Dopo un brevissimo riepilogo di alcuni concetti generali, per il resto questa introduzione si dipanerà attraverso la presentazione e la discussione di alcuni esempi.
I sorgenti verranno copiati da questa pagina Web in un editor di testo (o in Idle), eventualmente modificati e lanciati in esecuzione.

Aspetti generali

Architettura client-server

Secondo la solita Wikipedia:
Un sistema client-server (letteralmente cliente-servente) è un'architettura di rete nella quale un computer client istanzia l'interfaccia utente di un'applicazione connettendosi ad una server application o ad un sistema di database.
Più semplicemente, i sistemi client/server sono un'evoluzione dei sistemi basati sulla condivisione semplice delle risorse.
La presenza di un server permette ad un certo numero di client di condividere delle risorse, lasciando che sia il server a gestire gli accessi alle risorse per evitare conflitti di utilizzazione tipici dei primi sistemi informatici.

[Fine citazione]

In altre parole, in una applicazione client-server, l'obiettivo che si vuole raggiungere viene perseguito suddividendo le elaborazioni da svolgere tra due programmi distinti, detti per l'appunto client e server, che si ripartiscono i compiti in modo ottimale e colloquiano tra di loro mediante una connessione di rete. Noi ci occuperemo unicamente di connessioni di rete realizzate mediante il protocollo TCP/IP. Una volta che i due programmi sono collegati, il loro ruolo sulla rete è del tutto paritetico, ma ciò non ostante dal punto di vista dell'applicazione complessiva i ruoli del client e del server sono chiaramente distinti. In linea di massima, il server si occupa di gestire delle risorse mentre il client si occupa di offrire un'interfaccia all'utente.
Esempi tipici di applicazioni client-server con protocollo TCP/IP sono la distribuzione della posta elettronica (protocolli SMTP, POP3, IMAP), il trasferimento file (protocollo FTP), la consultazione delle pagine Web (protocollo HTTP).
Noi ci occuperemo dello sviluppo di applicazioni client-server con protocollo proprietario.

Vantaggi dell'architettura client-server

  1. Il carico computazionale viene ripartito tra due piattaforme in genere distinte. Ognuna di esse può essere ottimizzata per i compiti a cui è destinata: gestione di basi di dati, gestione di documenti, calcolo numerico, gestione di strumentazione, interfaccia utente.
  2. L'architettura si presta in modo naturale alla condivisione delle risorse: le risorse gestite dal server sono accessibili in teoria da qualunque nodo di Internet; se il server è realizzato in modo concorrente, l'accesso può avvenire da più nodi simultaneamente.
  3. Client e server possono:
    • essere sviluppati su piattaforme (cioè sistemi operativi) diversi; tutti i moderni sistemi operativi supportano infatti il protocollo TCP/IP;
    • essere sviluppati con linguaggi di programmazione diversi; tutti i moderni linguaggi di programmazione supportano infatti il protocollo TCP/IP;
    • essere sviluppati da programmatori diversi, creando così una modalità naturale di ripartizione del lavoro in un team.

Svantaggi dell'architettura client-server

  1. Maggior complessità del sistema.
  2. Dipendenza da una connessione di rete efficace.
  3. Procedura di sviluppo un po' più complicata.

Concetti di base di una applicazione client-server

Architettura client-server TCP/IP
La connessione TCP/IP stabilisce un collegamento punto-punto tra due applicazioni. Gli estremi di questo collegamento sono contrassegnati da un indirizzo IP, che identifica la workstation e da un numero di porta, che rende possibile la coesistenza, sulla stessa workstation, di più connessioni, facenti capo ad applicazioni indipendenti.
Le applicazioni che utilizzano il protocollo TCP/IP in un contesto client-server non solo devono conoscere ciascuna l'indirizzo IP e il numero di porta dell'altra, ma devono anche condividere il protocollo dell'applicazione, che pertanto deve essere stato preventivamente definito.
Una volta stabilita la connessione e il protocollo cui scambiare dati su di essa, il sottostante protocollo TCP/IP si incarica di far arrivare questi dati, suddivisi in pacchetti, da un estremo all'altro del collegamento. In particolare, il protocollo TCP si occupa di assemblare e disassemblare i pacchetti e di gestire l'handshaking che garantisce l'affidabilità della connnessione, mentre il protocollo IP si occupa del trasporto dei singoli pacchetti e della scelta del miglior instradamento degli stessi lungo la rete. Questo meccanismo è alla base della robustezza del protocollo TCP/IP nel suo insieme, che a sua volta rappresenta una delle motivazioni dello sviluppo del protocollo stesso in ambito militare (ARPAnet).
Le varie applicazioni standard esistenti (navigazione Web, trasferimento file, posta elettronica e molte altre) utilizzano protocolli di applicazione standardizzati (http, ftp, pop3, imap, smtp etc.). Ogni applicazione client-server specifica deve invece definire ed applicare il proprio protocollo di applicazione proprietario. Questo può prevedere lo scambio di dati in blocchi di dimensioni fisse (è la soluzione più semplice), oppure in forma di stringhe di testo terminate da CR+LF (è forse la soluzione più comune, che presenta il vantaggio di rendere facile il debug da parte di operatori umani) oppure ancora in blocchi delimitati in altro modo, con approcci ibdridi o diversi.

Il ruolo del server in una applicazione client-server

Il ruolo del client in una applicazione client-server

Ciò detto, iniziamo!

Viene presentato un modulo Python (anzi due, uno per l'ambiente testuale e uno per PyQt) che permette di realizzare applicazioni client-server in modo piuttosto elementare. Ci soffermeremo più sull'applicazione dei moduli che sulla loro implementazione.
I moduli hanno le loro radici in una libreria C che, assieme ad Alessandro Agostini, sviluppammo verso la fine del 1995 per gestire in modo semplice il colloquio client-server nel nascente sistema di acquisizione delle firme elettroniche dell'allora IROE, superando una certa farraginosità insita nel supporto nativo offerto dal linguaggio. La libreria fu sviluppata per le piattaforme Linux (gcc) e DOS (TurboC con supporto TCP/IP Ftp Software e Wattcp).
Successivamente, ho portato la libreria (in genere con qualche limitazione) in altre piattaforme, via via che se n'è presentata l'esigenza o l'opportunità: C/C++ sotto Win32 (client e server); VB6 sotto Win32 (solo client e senza supporto ai trasferimenti binari), PHP (idem) ed infine Python (client e server, per ora senza supporto ai trasferimento binari).

Risorse:

Funzioni di servizio

Un client HTTP minimale

Notare:

Un client general purpose orientato alla riga

Notare:

Un server iterativo

Notare:

Un server concorrente

Notare:


Il modulo tcpstream.py

Un client general purpose orientato al carattere

Notare:

Un server a doppia porta

Notare:

Un server iterativo per controllo strumentazione

Notare:

Un client general purpose PyQt orientato alla riga

Notare:

Un client PyQt per controllo remoto strumentazione

Notare:

Un server PyQt concorrente per controllo strumentazione (senza gestione conflitti)

Notare:

Un server PyQt concorrente per controllo strumentazione (con gestione conflitti)

Notare:


Ritorna alla pagina indice

Daniele Andreuccetti, IFAC-CNR, febbraio 2013