Calcolatori Elettronici

Slides:



Advertisements
Presentazioni simili
INFORMATICA Altre Istruzioni di I/O
Advertisements

LINGUAGGIO DI PROGRAMMAZIONE C
Acquisire ed elaborare immagini - Terza parte
Introduzione al linguaggio C
Socket Java Alberto Ferrari.
PHP.
Programmazione con socket
Algoritmi e Programmazione
SC che operano su processi
Reti di Calcolatori L’interfaccia socket
1 System Call per Comunicazione tra Processi Pipe.
SC che operano su file (1)
Programmazione socket
Esercitazione con socket
Giuseppe Fabio Fortugno.
Programmazione Procedurale in Linguaggio C++
Come programmare servizi di rete?
Indirizzi delle variabili A ogni variabile sono associati tre concetti fondamentali: il valore memorizzato; il tipo dati di appartenenza; lindirizzo. Il.
Argomenti dalla linea dei comandi Gli argomenti possono essere passati a qualsiasi funzione di un programma, compresa la main(), direttamente dalla linea.
Funzioni definite dall’utente
Calcolatori Elettronici
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Stringhe e Puntatori Marco D. Santambrogio – Ver. aggiornata al 18 Marzo 2013.
1 Corso di Laurea in Biotecnologie Informatica (Programmazione) Introduzione a JAVA Anno Accademico 2009/2010.
Il modello cliente/servente per l’implementazione di applicazioni
Introduzione alla programmazione lll
I Thread.
Fondamenti di Informatica I a.a Il linguaggio C Il controllo di flusso La selezione condizionale Listruzione switch I cicli Le istruzioni break,
INFORMATICA Altre Istruzioni di I/O. © Piero Demichelis 2 Funzioni di I/O Per la lettura e la scrittura da videoterminale il C prevede numerose istruzioni.
A.A. 2010/2011Ambienti di Programmazione per il Software di Base1 (Es. – 6) Ambienti di Programmazione per il Software di Base Le Stringhe in C Input.
1 LINUX: struttura generale The layers of a UNIX system. User Interface.
Strutture di controllo nel C
I File.
4 Cosa è una rete? ã Punto di vista logico: sistema di dati ed utenti distribuito ã Punto di vista fisico: insieme di hardware, collegamenti, e protocolli.
Reti di Calcolatori1 Il modello Client/Server La comunicazione Se sintetizziamo uno scenario completo possiamo identificare diverse interfacce.
GESTIONE DEI FILE Per poter mantenere disponibili i dati tra le diverse esecuzioni di un programma (persi-stenza dei dati) è necessario poterli archi-viare.
Corso di Informatica per Giurisprudenza Lezione 7
Cosa è una applicazione distribuita?
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli.
1 Ripassino Reti di Computer Carasco 19/02/ Che cosa è una rete informatica? Una rete informatica è un insieme di computer connessi tra di loro.
File system distribuito transazionale con replicazione
ISTITUTO STATALE DI ISTRUZIONE SUPERIORE F. ENRIQUES CORSO JAVA – PROVA INTERMEDIA DEL 12 MARZO 2007 NOME: COGNOME: ________________________________________________________________________________.
Calcolo della Subnet Mask e i protocolli SMB e NetBIOS
Distributed System ( )7 TCP/IP four-layer model.
Programmazione in linguaggio C
Come comunicano i processi ?
Creato da Riccardo Nuzzone
Politecnico di Milano © Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano
Fondamenti di Informatica II Ingegneria Informatica (A-I) Prof. M.T. PAZIENZA a.a – 3° ciclo.
1 SC che operano su processi Getpid, fork, exec, wait, waitpid, exit, dup, dup2.
1 Chiamate di sistema Introduzione Errori : perror() Chiamate che lavorano su file.
Operatori di incremento e decremento
Sistemi di elaborazione dell’informazione Modulo 4 -Tecniche di programmazione distribuita Unità didattica 1 - Socket library Ernesto Damiani Lezione 3.
Sistemi di elaborazione dell’informazione Modulo 4 -Tecniche di programmazione distribuita Unità didattica 1 -Socket library Ernesto Damiani Lezione 1.
Sistemi di elaborazione dell’informazione Modulo 4 - Tecniche di programmazione distribuita Unità didattica 1 - Socket library Ernesto Damiani Lezione.
Sistemi operativi di rete Ing. A. Stile – Ing. L. Marchesano – 1/18.
Sistemi di elaborazione dell’informazione Modulo 4 - Tecniche di programmazione distribuita Unità didattica 1 -Socket library Ernesto Damiani Lezione 2.
1.1 Corso di Sistemi Operativi: Programmazione di Sistema Corso di Laurea in Informatica, Università di Firenze Anno accademico 2010/2011 Prof. Luca Ferrari.
Sistemi di elaborazione dell’informazione Modulo 4 - Tecniche di programmazione distribuita Unità didattica 1 -Socket library Ernesto Damiani Lezione 4.
Linguaggio C: Le basi Stefano Cagnoni e Monica Mordonini
1 System Call che operano su processi Getpid, fork, exec, wait, waitpid, exit, dup, dup2.
Il centro stella puo’ essere realizzato con : Lavora solo a livello fisico (layer 1) : ripete esattamente su tutte le proprie porte il segnale arrivato.
Eprogram informatica V anno. Introduzione a PHP Introduzione La diffusione di PHP ha avuto un notevole incremento dalla fine degli anni Novanta a oggi,
Il C `e un linguaggio di programmazione di uso generale, originariamente sviluppato per la scrittura del sistema operativo Unix, ed oggi disponibile su.
Applicazione Presentazione Sessione Trasporto Rete Data link Fisico OSI Processo / Applicazione Trasporto Rete- Internet Interfaccia di.
1 Il livello transport. Concetti fondamentali - Canale logico e canale fisico 2 Quando un segnale deve essere trasmesso, viene inviato su un Canale, cioè.
Sezione propedeutica I fondamentali e concetti di TCP/IP.
Socket programming in Java La realizzazione di un server in Java consente di scrivere una sola versione eseguibile su diverse piattaforme. Il linguaggio.
Socket programming in Java La realizzazione di un server in Java consente di scrivere una sola versione eseguibile su diverse piattaforme. Il linguaggio.
Transcript della presentazione:

Calcolatori Elettronici Socket Calcolatori Elettronici C.Brandolese

Calcolatori Elettronici Sommario Introduzione Interfaccie e protocolli Il modello Client/Server Indirizzamento Connessione Strutture dati e costanti Funzioni di utilità Gestione dei socket Esempi Calcolatori Elettronici

Calcolatori Elettronici Introduzione Una applicazione è un insieme di programmi coordinati in modo da svolgere una determinata funzione: la funzione applicativa In un ambiente di programmazione usuale una applicazione coincide generalmente con un singolo programma. In un ambiente distribuito si parla di applicazioni distribuite Applicazione distribuita: E’ costituita da un insieme di programmi che vengono generalmente eseguiti su macchine diverse I vari programmi cooperano attraverso una rete di calcolatori Le applicazioni distribuite richiedono la capacità di comunicare attraverso una rete. Calcolatori Elettronici

Calcolatori Elettronici Introduzione I vari programmi che costituiscono una applicazione distribuita devono seguire alcune regole per comunicare in modo corretro L’insieme delle regole per la comunicazione prende il nome di protocollo applicativo Si noti che, come è ovvio, due programmi comunicano tra di loro solo quando sono in esecuzione: a rigore quindi sono i processi a comunicare sulla base delle istruzioni constenute nei programmi Nel seguito si parlerà indifferentemente di processi o di programmi, intendendo quanto appena chiarito Calcolatori Elettronici

Interfaccie e protocolli Per la comunicazione i programmi di una applicazione distribuita si appoggiano a un insieme di servizi tipici forniti: Dal sistema operativo Dal software di rete Il programmatore utilizzare in pratica delle funzioni di libreria L’insieme delle funzioni di base prende il nome di Application Program Interface o API E’ bene notare la differenza tra protocollo applicativo e API: Il protocollo applicativo rappresenta le regole per la comunicazione, ma non è un canale diretto di comunicazione Le API sono le funzioni che realizzano sul canale fisico le regole di comunicazione definite nel protocollo. Calcolatori Elettronici

Interfaccie e protocolli Esempio di applicazione distribuita: APPLICAZIONE DISTRIBUTA PROGRAMMA APPLICATIVO PROGRAMMA APPLICATIVO Protocollo Applicativo API API Sistema Operativo e Software di Rete Sistema Operativo e Software di Rete RETE Calcolatori Elettronici

Interfaccie e protocolli Nel seguito faremo riferimento ai sistemi operativi: UNIX WindowsNT Supporremo inoltre che il software di rete disponibile sia TCP/IP TCP/IP definisce in maniera astratta alcuni servizi che i vari sistemi operativi realizzano e rendono disponibili tramite le API Uno dei servizi forniti dal protocollo TCP/IP è l’interfaccia: SOCKET (UNIX) WINSOKET (WindowsNT) Calcolatori Elettronici

Interfaccie e protocolli La configurazione di riferimento di una applicazione distribuita basata su TCP/IP e soket è il seguente: PROGRAMMA C Protocollo Applicativo PROGRAMMA C UNIX API + SOKET NT API + WINSOKET UNIX + TCP/IP Canale WindowsNT + TCP/IP Calcolatori Elettronici

Il modello Client/Server Il protocollo TCP/IP fornisce un meccanismo di comunicazione tra processi residenti su macchine diverse Il tipo di comunicazione è detto peer-to-peer (da pari a pari) Sta al programmatore definire le regole di comunicazione cioè il protocollo applicativo Molte applicazioni sono basate sul modello Client/Server In questo modello una delle applicazioni agisce da Server mentre le altre agiscono da Client In generale un processo può assumere il ruolo di Client o di Server dinamicamente nel tempo Calcolatori Elettronici

Il modello Client/Server Il processo Server: Fornisce servizi Accetta richieste provenienti dai client Esegue i servizi richiesti Eventualmente ritorna un risultato al richiedente Il processo Client: Richiede servizi ad un server Attende una risposta da parte del server Ad esempio: Server: WEBServer Client: Browser Calcolatori Elettronici

Calcolatori Elettronici Indirizzamento Quando un processo P intende comunicare con un processo Q, in esecuzione su un’altra macchina deve: Identificare la macchina su cui è in esecuzione Q Identificare il processo Q fra tutti quelli in esecuzione sulla macchina Una macchina è individuata dal suo indirizzo IP: Un indirizzo IP è un numero di 32 bit univoco all’interno di una rete Gli indirizzi IP vengono scritti esprimendo il valore decimale dei 4 gruppi di 8 bit che lo compongono, separati da un punto Un processo è individuato attraverso un port: Un port è un numero usato per identificare un processo solo ai fini della comunicazione TCP/IP Il port di un processo non ha nessuna relazione con il suo pid Calcolatori Elettronici

< IP_Address, Port > Indirizzamento Port e pid identificano un processo ma: Il pid di un processo è assegnato dal sistema operativo ed il programmatore non ha alcun controllo sul suo valore Il port viene assegnato dal programmatore Affinché il processo P possa comunicare con il processo Q, i due programmi devono stabilire un port con cui identificarsi I port da 0 a 1023 sono utilizzati da servizi standard e non possono essere usati dal programmatore Un idirizzo TCP completo è quindi costituito dalla coppia: < IP_Address, Port > Calcolatori Elettronici

Calcolatori Elettronici Connessione La comunicazione in TCP si dice orientata alla connesione Questo significa che, prima di poter scambiare dati, due processi devono stabilire una connessione In un modello client/server, per stabilire una connessione tra due processi P e Q è necessario che: Il processo P, che agisce da server, si metta in attesa di richieste da parte del processo Q Il processo Q, che agisce da client, invia richieste al processo P ed attende una risposta Quando il server P accetta una richiesta di un servizio da parte del processo Q si stabilisce la connessione Calcolatori Elettronici

Calcolatori Elettronici Connessione Aspetti generali di una connessione: I due processi che stabiliscono una connessione sono detti punti terminali Ogni processo è identificato dalla coppia <IP_Address, Port> La connessione è identificata dai suoi punti terminali cioè dalle due coppie <IP_Address, Port> relative appunto ai punti terminali Dopo aver stabilito la connessione, i processi dispongono di un canale: Bidirezionale: la comunicazione può avvenire nelle due direzioni Affidabile: un meccanismo di acknowledge garantisce che i dati siano ricevuti Orientato allo stream: i dati vengono trasmessi in modo continuo Si noti che l’identificazione della connessione consente ad un processo di partecipare a diverse connessioni in quanto TCP le distingue in base agli indirizzi dei punti terminali Calcolatori Elettronici

Strutture dati e costanti Gli indirizzi di socket sono memorizzati in una struttura dati C: struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; Il significato dei campi è il seguente sin_family: famiglia degli indirizzi. Nel nostro caso AF_INET. sin_port: numero del port. Compreso tra 0 e 64k sin_addr: indirizzo IP. Si tratta di una union di cui useremo solo il campo s_addr di tipo u_long, cioè intero a 32 bit senza segno sin_zero: non utilizzato Calcolatori Elettronici

Strutture dati e costanti Sono definiti alcuni gruppi di costanti Costanti per la definizione del tipo di indirizzo AF_UNIX: Indirizzi ARPA, locali alle macchine AF_INET: Indirizzi Internet Costanti per la definizione del tipo di comunicazione: SOCK_STREAM: Orientata allo stream SOCK_DGRAM: Datagram SOCK_RAW: Raw data Queste costanti vengono utilizzate nella creazione dei socket e nella definizione degli indirizzi Calcolatori Elettronici

Calcolatori Elettronici Funzioni di utilità Conversione da stringa a indirizzo IP: unsigned long inet_addr(const char *cp); Conversione da formato host a formato network uint32_t htonl(unint32_t hostlong); uint16_t htons(uint16_t hostshort); Conversione da formato network a formato host uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort); Calcolatori Elettronici

Calcolatori Elettronici Gestione dei socket Creazione di un socket: int socket(int domain, int type, int protocol); I parametri hanno il seguente significato: domain: famiglia di protocolli, nel nostro caso AF_INET type: tipo di connessione, nel nostro caso SOCK_STREAM protocol: tipo di protocollo, nel nostro caso esiste solo il protocollo IP quindi questio parametro vale generalmente 0 Crea un socket con le caratteristiche specificate e restituisce un descrittore Il descrittore è simile al descrittore utilizzato per la gestione dei files Calcolatori Elettronici

Calcolatori Elettronici Gestione dei socket Chiusura di un socket: int close(int socket); I parametri hanno il seguente significato: socket: descrittore di socket Chiude il socket individuato dal descrittore specificato Dopo la chiusura, il socket non è più accessibile Calcolatori Elettronici

Calcolatori Elettronici Gestione dei socket Associazione di un socket ad un indirizzo locale: int bind(int s, struct sockaddr *locaddr, int locaddrlen); I parametri hanno il seguente significato: s: descrittore di socket locaddr: indirizzo IP local al quale il socket viene associato locaddrlen: dimensioni della struttura dati utilizzata per specificare l’indirizzo locale. Generalmente si ottiene tramite la funzione standard sizeof() Lega il socket il cui descrittore è s all’indirizzo locale specificato nella struttura dati locaddr. Questa funzione associa al socket uno dei due punti terminali Calcolatori Elettronici

Calcolatori Elettronici Gestione dei socket Dimensione della coda di un socket: int listen(int s, int backlog); I parametri hanno il seguente significato: s: descrittore di socket backlog: dimensione massima della coda di richieste Specifica il numero massimo di richieste che possono essere messe in coda sul socket s Una richiesta che arrivi quando la coda è piena viene rifutata ed il processo richiedente riceve un messaggio di errore Calcolatori Elettronici

Calcolatori Elettronici Gestione dei socket Accettazione di una richiesta di connessione: int accept(int s, struct sockaddr *destaddr, int *destaddrlen); I parametri hanno il seguente significato: s: descrittore di socket destaddr: indirizzo del processo richiedente destaddrlen: dimensione della struttura dati contenete l’indirizzo del processo richiedente Accetta la prima richiesta di connessione in coda, crea un nuovo socket e ne restituisce il descrittore Il socket creato non può più essere utilizzato per accettare altre richieste mentre il socket originale si Calcolatori Elettronici

Calcolatori Elettronici Gestione dei socket Crea una connessione: int connect(int s, struct sockaddr *destaddr, int *destaddrlen); I parametri hanno il seguente significato: s: descrittore di socket destaddr: indirizzo del processo remoto richiedente destaddrlen: dimensione della struttura dati contenete l’indirizzo del processo richiedente Crea una connessione, nel nostro caso TCP/IP, con il richiedente il cui indirizzo è specificato dagli ultimi due parametri Dopo la creazione della connessione i due processi possono iniziare lo scambio di dati Calcolatori Elettronici

Calcolatori Elettronici Gestione dei socket Scrive/legge dati attraverso un socket: int write(int fd, char *buf, int nbyte); int read (int fd, char *buf, int nbyte); I parametri hanno il seguente significato: fd: descrittore di socket (o di file) buf: puntatore all’area dati nbyte: dimensione dei dati Legge o scrive dati attraverso un socket Queste funzioni sono le stesse utlizzate per la lettura scrittura di dai da/verso i files Calcolatori Elettronici

Esempio: Client/Server – Singola connessione Il server: Legge dalla linea di comando il numero di porta crea un socket su quella porta Aspetta chiamate Ogni volta che arriva una chiamata: Legge da socket un comando e lo esegue Scrive il risultato sullo stesso socket Chiude la connessione Si rimette in attesa Il ciclo di attesa non termina mai Per terminare il processo server occorre ucciderlo (kill) esplicitamente Calcolatori Elettronici

Esempio: Client/Server – Singola connessione Il client: Legge dalla linea di comando l'indirizzo IP e il numero di port del server Crea un socket Si connette al server Legge un comando da standard input Invia il comando al server Legge la risposta Trascrive la risposta su standard output Chiude la connessione Termina Ogni volta che il client è invocato comunica un solo comando al server Calcolatori Elettronici

Esempio: Client/Server – Singola connessione Il server è organizzato come segue: Creazione del socket socket() Inizializzazione dell’indirizzo: contenuto nella variabile server_addr il tipo è struct sockaddr_in Binding del socket bind() Definizione del numero massimo di connessioni listen() Ciclo infinito, in cui: Accetta una connessione accept() Legge un comando da socket read() Scrive il risultato dell’esecuzione del comando su socket write() Termina la connessione close() Calcolatori Elettronici

Esempio: Client/Server – Singola connessione #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h>   #define MAX_CONN 5 int main(int argc, char* argv[]) { int sock_fd; int new_sock_fd; int client_len; struct sockaddr_in server_addr; struct sockaddr_in client_addr; char command; if( argc != 2 ){ printf(“Numero di parametri errato\n”); exit(1); } sock_fd = socket(AF_INET, SOCK_STREAM, 0); ... Calcolatori Elettronici

Esempio: Client/Server – Singola connessione ... server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons((u_short) atoi(argv[1]));   bind( sock_fd, (struct sockaddr *) &server_addr, sizeof(server_addr) ); listen(sock_fd, MAX_CONN); Calcolatori Elettronici

Esempio: Client/Server – Singola connessione ... while(1) { new_sock_fd = accept( sock_fd, (struct sockaddr *) &client_addr, &client_len ); read(new_sock_fd, &command, 1); switch (command) { case 'a': write(new_sock_fd, "SERVICE_A", strlen("SERVICE_A") ); break; case 'b': write(new_sock_fd, "SERVICE_B", strlen("SERVICE_B") ); break; default: write(new_sock_fd, "UNKNOWN", strlen("UNKNOWN") ); break; } close(new_sock_fd); Calcolatori Elettronici

Esempio: Client/Server – Singola connessione Il client è organizzato come segue: Creazione del socket socket() Inizializzazione dell’indirizzo: L’indirizzo IP è in argv[1] Il port del server è in argv[2] Connessione al server connect() Legge un comando da standard input Scrive il comando sul soket write() Legge il risultato dal socket read() Scrive il risultato sullo standard output Chiude il socket e termina close() Calcolatori Elettronici

Esempio: Client/Server – Singola connessione #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h>   int main(int argc, char* argv[]) { int sock_fd; int err; struct sockaddr_in server_addr; char command; char result; if (argc != 3) { printf(“Numero di parametri errato\n”); exit(1); } sock_fd = socket(AF_INET, SOCK_STREAM, 0); ... CLIENT Calcolatori Elettronici

Esempio: Client/Server – Singola connessione server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr( argv[1] ); server_addr.sin_port = htons( (u_short)atoi(argv[2]) ); err = connect( sock_fd, (struct sockaddr *) &server_addr, sizeof(server_addr) ); if( err < 0 ) exit(1); read(0, &command, 1); write(sock_fd, &command, 1); while( read( sock_fd, &result, 1 ) ) write( 1, &result, 1 ); close( sock_fd ); } CLIENT Calcolatori Elettronici

Esempio: Client/Server – Più connessioni Il server: Legge dalla linea di comando il numero di porta Crea un socket su quella Aspetta chiamate Ogni volta che arriva una chiamata: Genera un processo figlio, che gestirà la connessione Il processo padre chiude la connessione e si rimette in attesa Il processo figlio legge da socket un comando Esegue il comando e scrive il risultato sullo stesso socket Ripete la sequenza di gestione dei comandi finché non riceve il comando di uscita Chiude la connessione e termina Calcolatori Elettronici

Esempio: Client/Server – Più connessioni Il server è organizzato come segue: Creazione del socket socket() Inizializzazione dell’indirizzo: contenuto nella variabile server_addr il tipo è struct sockaddr_in Binding del socket bind() Definizione del numero massimo di connessioni listen() Ciclo infinito, in cui: Accetta una connessione e crea un figlio accept() Il figlio legge un comando da socket read() Il figlio scrive un risultato sul socket write() Il figlio terminala connessione close() Il padre terminala connessione close() Calcolatori Elettronici

Esempio: Client/Server – Più connessioni #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h>   #define MAX_CONN 5 int main(int argc, char* argv[]) { int sock_fd, new_sock_fd; int client_len; int pid; char command;   struct sockaddr_in server_addr; struct sockaddr_in client_addr; if (argc != 2) { printf(“Numero di parametri errato\n”); exit(1); } SERVER Calcolatori Elettronici

Esempio: Client/Server – Più connessioni ... sock_fd = socket(AF_INET, SOCK_STREAM, 0); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons((u_short) atoi(argv[1]));   bind( sock_fd, (struct sockaddr *) &server_addr, sizeof(server_addr) ); listen(sock_fd, MAX_CONN);  ... Calcolatori Elettronici

Esempio: Client/Server – Più connessioni while( 1 ) { new_sock_fd = accept( sock_fd, (struct sockaddr *) &client_addr, &client_len ); pid = fork(); if( pid == 0 ) { do { read( new_sock_fd, &command, 1 ); execute_command( new_sock_fd, command ); } while( command != 'q‘ ); close( new_sock_fd ); exit( 0 ); } else {   close( new_sock_fd ); } SERVER child Calcolatori Elettronici

Esempio: Client/Server – Più connessioni Il server si aspetta una sequenza di comandi terminata dal carattere q I client gestiscono una sequenza di comandi Nel codice seguente si mostra solamente ciò che accade dopo l’apertura della connessione La parte di codeice del client qui omessa è molto simile al codice visto per la connessione singola Calcolatori Elettronici

Esempio: Client/Server – Più connessioni #define MAXSTR 4096 char command; int nbytes; char buf[MAXSTR]; ... while( 1 ) { read( 0, &command, 1 ); write( sock_fd, &command, 1 ); if( command == ‘q‘ ) break; nbytes = read( sock_fd, buf, MAXSTR); write( 1, buf, nbytes ); } close( sock_fd ); CLIENT Calcolatori Elettronici