I/O su Socket TCP: read()



Documenti analoghi
Esercitazione [5] Input/Output su Socket

J+... J+3 J+2 J+1 K+1 K+2 K+3 K+...

IPC System V. Code di messaggi

Gestione dei File in C

I puntatori e l allocazione dinamica di memoria

Sincronizzazione e comunicazione tra processi in Unix. usati per trasferire ad un processo l indicazione che un determinato evento si è verificato.

Lab. di Sistemi Operativi - Esercitazione n 9- -Thread-

Strutture. Strutture e Unioni. Definizione di strutture (2) Definizione di strutture (1)

Comunicazione. La comunicazione point to point e' la funzionalita' di comunicazione fondamentale disponibile in MPI

rsystem Maximiliano Marchesi

Funzioni in C. Violetta Lonati

10.1. Un indirizzo IP viene rappresentato in Java come un'istanza della classe InetAddress.

Cenni di programmazione distribuita in C++ Mauro Piccolo

HTTP adaptation layer per generico protocollo di scambio dati

Introduzione alla programmazione in C

Per scrivere una procedura che non deve restituire nessun valore e deve solo contenere le informazioni per le modalità delle porte e controlli

ESERCIZI DI PROGRAMMAZIONE C IN AMBIENTE UNIX

Esercizio 2. Client e server comunicano attraverso socket TCP

Laboratorio di Sistemi Operativi

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

Esercitazione [6] Client/Server con Socket

Opzioni del Socket. Socket Options. Opzioni di Livello Socket. Livello delle Opzioni

Esercizi (1-2): da: TCP/IP Sockets in C (Donahoo-Calvert)

Sistema operativo: Gestione della memoria

Inizializzazione, Assegnamento e Distruzione di Classi

Gestione Risorse Umane Web

Inter-Process Communication

Funzioni. Il modello console. Interfaccia in modalità console

Automatizzare i compiti ripetitivi. I file batch. File batch (1) File batch (2) Visualizzazione (2) Visualizzazione

STRUTTURE DEI SISTEMI DI CALCOLO

I file di dati. Unità didattica D1 1

Introduzione al Linguaggio C

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

TERMINALE. Creazione e gestione di una postazione terminale di Eureka

Sistemi Operativi (modulo di Informatica II)

void funzioneprova() { int x=2; cout<<"dentro la funzione x="<<x<<endl; }

MANUALE UTENTE Fiscali Free

OTTAVA ESPERIENZA DI LABORATORIO. L elaborazione dei files in C

Lab. di Sistemi Operativi - Esercitazione n 7- -Gestione dei processi Unix-

Arduino: Programmazione

Veneto Lavoro via Ca' Marcello 67/b, Venezia-Mestre tel.: 041/

Socket. Nei sistemi operativi moderni i servizi disponibili in rete si basano principalmente sul modello client/server.

Introduzione alle applicazioni di rete

FPf per Windows 3.1. Guida all uso

Socket TCP. prima parte

Le funzioni in C. I programmi C sono costituiti da definizioni di variabili e funzioni.

Thread: sincronizzazione Esercitazioni del 09 Ottobre 2009

Allocazione dinamica della memoria - riepilogo

ROM Upgrade Utility (RUU) Prima dell aggiornamento fare attenzione se

4.1 FAX Sollecito consegne via (Nuova funzione)

I Socket. Laboratorio Software M. Grotto R. Farina

CALCOLATORI ELETTRONICI A cura di Luca Orrù. Lezione n.7. Il moltiplicatore binario e il ciclo di base di una CPU

POSIX - Gestione dei Segnali. E.Mumolo, DEEI mumolo@units.it

CONFIGURAZIONE SERVER APACHE (XAMPP): ACCESSO SICURO A DIRECTORY DEL FILE SYSTEM.

Gestione dei processi

Programmazione dei socket con TCP #2

Esempio produttori consumatori. Primitive asincrone

Sistema di gestione Certificato MANUALE PER L'UTENTE

2.5. L'indirizzo IP identifica il computer di origine, il numero di porta invece identifica il processo di origine.

dall argomento argomento della malloc()

Siamo così arrivati all aritmetica modulare, ma anche a individuare alcuni aspetti di come funziona l aritmetica del calcolatore come vedremo.

Input/Output. Moduli di Input/ Output. gestiscono quantità di dati differenti a velocità diverse in formati diversi. n Grande varietà di periferiche

System call fcntl e record locking

Istruzioni per il pagamento con Carta di Credito

Sicurezza e rispetto della privacy, finalmente non in conflitto.

Esercitazione. Formato di compitini e compiti: domande ed esercizi "closed book" G. Ferrari - Reti di calcolatori.

Servizio di Posta elettronica Certificata (PEC)

Gli array. Gli array. Gli array. Classi di memorizzazione per array. Inizializzazione esplicita degli array. Array e puntatori

Realizzazione di Politiche di Gestione delle Risorse: i Semafori Privati

COMUNICAZIONE UTENTI SISTEMI-PROFIS INSTALLAZIONE GE.RI.CO e PARAMETRI2015

Socket & RMI Ingegneria del Software - San Pietro

BARCODE. Gestione Codici a Barre. Release 4.90 Manuale Operativo

Impostazione dell'indirizzo IP del dispositivo di autenticazione di Xerox Secure Access Unified ID System Carta bianca

Descrizione di un algoritmo

Corso di Sistemi Operativi Ingegneria Elettronica e Informatica prof. Rocco Aversa. Raccolta prove scritte. Prova scritta

Esercizio sulla gestione di file in Unix

Matlab: Gestione avanzata dei file

DNS-Tunneling. Reference to. Ettore di Giacinto Luca Montunato

Fondamenti di Informatica T-1, 2009/2010 Modulo 2 Prova d Esame 5 di Giovedì 15 Luglio 2010 tempo a disposizione 2h30'

Pronto Esecuzione Attesa Terminazione

Interprocess Communications - II. Franco Maria Nardini

Università degli Studi di Cassino Corso di Fondamenti di Informatica Puntatori. Anno Accademico 2010/2011 Francesco Tortorella

Introduzione al linguaggio C Gli array

Drivers. Introduzione Tipologie Struttura Interazione con il kernel

Transcript:

I/O su Socket TCP: read() I socket TCP, una volta che la connessione TCP sia stata instaurata, sono accedibili come se fossero dei file, mediante un descrittore di file (un intero) ottenuto tramite una socket() o una accept() o una connect(). Con questo descrittore è possibile effettuare letture tramite la funzione read, che restituisce i byte letti dal flusso in entrata, e scritture tramite le funzioni write e send, che spediscono i byte formando il flusso in uscita. ssize_t read (int fd, void *buf, size_t count); cerca di leggere count byte dal file descriptor fd, scrivendoli nel buffer puntato da buf. Se count è zero la read restituisce zero. Se count è maggiore di zero viene effettuata la lettura e viene restituito il numero di byte letti (maggiore di zero, se tutto è OK). - Se viene restituito 0 (zero) significa end-of-file (fine stream), ovvero significa che l altro end system ha volutamente chiuso la connessione e quindi il socket non potrà essere più utilizzato per leggere. - Se viene restituito -1 è accaduto un errore e viene settata la variabile globale errno definita in <errno.h> con un valore che indica quale errore è avvenuto. In particolare, se errno vale EINTR significa che il sistema operativo ha dovuto interrompere la system call read, ma il socket non è in stato di errore, quindi la read può essere ripetuta immediatamente con gli stessi parametri. Altro caso particolare è quando il socket è stato definito non bloccante nel qual caso se non ci sono byte disponibili viene restituito EAGAIN, ed il socket rimane utilizzabile. Se invece errno ha un altro valore (EBADF, EINVAL, EFAULT, ) il socket viene invalidato. La funzione read, applicata ad un socket, presenta una particolarità. Può accadere che la read() restituisca meno byte di quanti richiesti, anche se lo stream è ancora aperto. Ciò accade se il buffer a disposizione del socket nel kernel è stato esaurito. Sarà necessario ripetere la read (richiedendo il numero dei byte mancanti) fino ad ottenerli tutti. Oss.: 101a ssize_t è definito in <unistd.h> ed è un long.

I/O su Socket TCP: write() (1) ssize_t write (int fd, const void *buf, size_t count); cerca di scrivere fino a count byte nel buffer di sistema corrispondente al file descriptor fd perché siano poi trasmessi. I byte vengono letti dal buffer puntato da buf. - Se count è zero la write restituisce zero e non scrive nulla. - Se count è maggiore di zero viene effettuata la scrittura e viene restituito il numero di byte scritti. - Se viene restituito -1 è accaduto un errore e viene settata la variabile errno con un valore che indica l errore. - Se il socket è configurato in modalità bloccante (è il default) la write è bloccante, cioè attende fino a che tutti i byte sono stati passati al buffer di sistema. Ciò significa che se non c è abbastanza spazio nel buffer di sistema la write attende fino a che non sono stati spediti abbastanza byte da permettere la scrittura di tutti i byte passati. Durante questa attesa può capitare che al processo arrivi un segnale (es SIGUSR1) che deve essere gestito dal processo stesso; in tal caso la write termina restituendo il numero di byte scritti sul buffer di sistema. Se invece nessun byte è stato ancora scritto viene restituito -1 e indicato l errore EINTR. - Se invece il socket è configurato in modalità non bloccante la write scrive sul buffer di sistema il maggior numero di byte possibile senza produrre attesa e poi termina restituendo il numero di byte scritti. Se non è stato possibile scrivere nulla la write restituisce -1 senza attendere e setta errno al valore EAGAIN. Altri possibili errori sono EBADF (file descriptor non valido), EINVAL (file descriptor non permette scritture), EFAULT (il buffer buf è fuori dallo spazio di memoria permesso), EPIPE (il socket è stato chiuso dall altro end system). 101b

I/O su Socket TCP: write() (2) Indipendentemente da come i socket sono stati settati, nel momento in cui viene invocata la write può capitare che il processo venga terminato dall arrivo di un segnale SIGPIPE che viene generato dalla write stessa per indicare che il socket che si sta usando è stato chiuso in modo anormale dall altro end system (inviando un segmento col flag reset) o che non è più utilizzabile. Per impedire la terminazione del processo ho due diverse possibilità: 1) istruire il processo per far intercettare i segnali SIGPIPE, nel qual caso la write invece di inviare il segnale restituirà -1 indicando come errore EPIPE. // da eseguire solo una volta, in fase di setup del processo if( signal(sigpipe, SIG_IGN) == SIG_ERR ) {perror("signal SIGPIPE failed: ");exit(1);.. // poi si possono fare tutte le chiamate alla write ris=write(socketfd, buff, n); if(ris<0){ if(errno==epipe) { printf( chiusura anomala\n );exit(1); Così però intercetto tutti i segnale SIGPIPE indipendentemente da quale socket (usato dal processo) lo provoca. 2) utilizzare al posto della write la system call send, in cui può essere specificato di non generare il segnale SIGPIPE ma di restituire -1 indicando come errore EPIPE. In questo modo, solo il segnale SIGPIPE di quella particolare invocazione viene intercettato. 101c

I/O su Socket TCP: send() (3) int send (int fd, const void *buf, size_t count, int flags); cerca di scrivere fino a count byte nel buffer di sistema corrispondente al file descriptor fd perché siano poi trasmessi. I byte vengono letti dal buffer puntato da buf. - Se count è zero la send restituisce zero e non scrive nulla. - Se count è maggiore di zero viene effettuata la scrittura e viene restituito il numero di byte scritti. - Se viene restituito -1 è accaduto un errore e viene settata la variabile errno con un valore che indica l errore. Il comportamento viene influenzato dal valore del parametro flags, il cui valore può essere 0 oppure viene assegnato mediante OR bit a bit delle seguenti costanti: MSG_OOB, MSG_DONTWAIT, MSG_NOSIGNAL. Se il valore di flags è zero la send si comporta come la write. Se viene specificato MSG_DONTWAIT la send non si blocca bensì scrive il numero di byte possibili nel buffer di sistema e termina restituendo il numero di byte scritti, eventualmente zero. Se viene specificato MSG_NOSIGNAL la send non solleva l eccezione di tipo SIGPIPE e quindi non rischia di far terminare il processo. Al contrario, in caso di chiusura anormale della connessione, restituisce -1 e setta la variabile errno al valore EPIPE. 101d

I/O su Socket TCP: (2) TCP Output Ogni socket TCP possiede un buffer per l output (send buffer) in cui vengono collocati temporaneamente i dati che dovranno essere trasmessi mediante la connessione instaurata. La dimensione di questo buffer può essere configurata mediante un opzione SO_SNDBUF. Quando un applicazione chiama write() per n bite sul socket TCP, il kernel cerca di copiare n byte dal buffer dell appl. al buffer del socket. Se il buffer del socket e più piccolo di n byte, oppure è già parzialmente occupato da dati non ancora trasmessi e non c è spazio sufficiente, verranno copiati solo nc<n byte, e verrà restituito dalla write il numero nc di byte copiati. Se il socket ha le impostazioni di default, cioè è di tipo bloccante, la fine della routine write ci dice che sono stati scritti sul buffer del socket quegli nc byte, e possiamo quindi riutilizzare le prime nc posizioni del buffer dell applicazione. Ciò non significa affatto che già i dati siano stati trasmessi all altro end-system. 102

I/O su Socket TCP : utility (1) Per attendere di ricevere almeno un byte, o leggere i byte già arrivati, si usa la già descritta ssize_t read (int fd, void *buf, size_t n); Per attendere di ricevere TUTTI i byte richiesti, si implementa la seguente funzione readn, che -restituisce -1 in caso di errore, e setta errno -restituisce il numero di byte letti se l altro end system chiude la connessione - restituisce il numero di byte chieste (e letti) se tutto ok. ssize_t readn (int fd, char *buf, size_t n) { size_t nleft; ssize_t nread; nleft = n; while (nleft > 0) { if ( (nread = read(fd, buf+n-nleft, nleft)) < 0) { if (errno!= EINTR) return(-1); // restituisco errore else if (nread == 0) { // EOF, connessione chiusa, termino // esce e restituisco il numero di byte letti break; else // continuo a leggere nleft -= nread; return(n - nleft); // return >= 0 103a

I/O su Socket TCP : utility (2) Per attendere di consegnare al buffer di sistema TUTTI i byte richiesti restituisce -1 in caso di errore e setta errno restituisce il numero di byte da inviare ed inviati, se tutto OK. ssize_t writen (int fd, const char *buf, size_t n) { size_t nleft; ssize_t nwritten; char *ptr; ptr = buf; nleft = n; while (nleft > 0) { if ( (nwritten = send(fd, ptr, nleft, MSG_NOSIGNAL )) < 0) { if (errno == EINTR) nwritten = 0; /* and call write() again*/ else return(-1); /* error */ nleft -= nwritten; return(n); ptr += nwritten; Per consegnare da zero ad n byte da trasmettere, ma senza attendere: restituisce -1 in caso di errore, se no restituisce il numero di byte scritti ssize_t write_nowait (int fd, const char *buf, size_t n) { int nwritten; do { nwritten=send ( fd, buf, n, MSG_DONTWAIT MSG_NOSIGNAL); while( (nwritten<0) && (errno==eintr) ); return(nwritten); 103b

Interazioni tra Client e Server TCP Per primo viene fatto partire il server, poi viene fatto partire il client che chiede la connessione al server e la connessione viene instaurata. Nell esempio (ma non è obbligatorio) il client spedisce una richiesta al server, questo risponde trasmettendo alcuni dati. Questa trasmissione bidirezionale continua fino a che uno dei due (il client nell esempio) decide di interrompere la connessione, e tramite la close() chiude la connessione. Infine il server chiude a sua volta la connessione. ephemeral port 104