Sono definiti per vari protocolli

Documenti analoghi
Laboratorio di Reti di Calcolatori

Progettazione di Applicazioni Robuste. Applicazione Echo. Schema Generale di un Server TCP Ricorsivo 1. Applicazione echo

Sviluppo di Applicazioni su Rete. Introduzione all API socket di Berkeley. Interazione tra Processi. Modello Client-Server

Laboratorio di Reti di Calcolatori

request reply richiesta client processo di servizio processo server principale From - Valeria Cardellini, Corso Sist. Distr. A.A.

Laboratorio di Reti di Calcolatori

Interazione con il DNS Conversioni di Nomi ed Indirizzi

Esercitazione [6] Client/Server con Socket

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

Socket TCP. prima parte

Esempio 1: stampa locale di file remoto

Socket per TCP: Fondamenti

Socket TCP. seconda parte

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

Interazione (TCP) Client-Server con le socket

(VHUFLWD]LRQLGLEDVHVXOOH6RFNHWLQ&

Esercitazione di Lab. di Sistemi Operativi 1 a.a. 2011/ Comunicazione Tra Processi (IPC) Parte -

I Socket. Laboratorio Software M. Grotto R. Farina

IPC Inter Process Communication

COMUNICAZIONE TRA PROCESSI REMOTI IN UNIX

Programmazione di applicazioni di rete

Socket per TCP: Fondamenti

Laboratorio di Sistemi Operativi Cognome Nome Mat.

Cenni di programmazione distribuita in C++ Mauro Piccolo

INGEGNERIA DEL WEB. VinX

Una semplice applicazione client/server 1

INTERNET DOMAIN SOCKETS (Cap.59)

DATAGRAM SOCKET. Angelastro Sergio Diomede Antonio Viterbo Tommaso

Creare una applicazione Winsock di base

Esercitazione Laboratorio di Sistemi Operativi Cognome Nome Mat.

Guida all' uso dei sockets nella programmazione in C

I/O su Socket TCP: read()

rsystem Maximiliano Marchesi

CORSO DI SISTEMI OPERATIVI A - ESERCITAZIONE 6

Creare un'elementare backdoor in C in ambiente UNIX

SC per Inter Process Comminication. Comunicazione fra macchine diverse: socket

Acknowledgment: Prof Vincenzo Auletta, Università di Salerno. Approfondimento alla programmazione distribuita

TECN.PROG.SIST.INF. TCP socket in Windows Roberta Gerboni

Inter-process communication: socket

unsigned long inet_addr(cp) char *cp;

programmazione distribuita Introduzione Introduzione alla programmazione distribuita

Paradigma client-server

Avviso ai programmatori. Programmazione in rete: i socket. Esercizio - copia dati. Messaggi di errore. stdarg.h. Funzioni di errore

Una socket è un punto estremo di un canale di comunicazione accessibile mediante un file descriptor. Alcuni tipi predefiniti di socket

Laboratorio di Programmazione in rete

Sistemi Operativi Anno Accademico 2011/2012. Segnali: Interrupt software per la gestione di eventi asincroni

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

Le Opzioni per i Socket

Esercitazione di Lab. di Sistemi Operativi 1 a.a. 2011/ Comunicazione Tra Processi (IPC)- - 1 Parte -

Program m azione di Sistem a 6

Basi di network programming sotto Unix/Linux (draft version) Claudio Piciarelli

Sicurezza delle reti. Monga. Ricognizione. Scanning Breve ripasso socket Network mapping Port Scanning NMAP. Le tecniche di scanning

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

Laboratorio di Programmazione in Rete

T.A.R.I. Socket (ICT, AL)

Elementi di programmazione con interfaccia Socket

Laboratorio di Programmazione in Rete

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

Programmazione dei socket di rete in GNU/Linux

HTTP adaptation layer per generico protocollo di scambio dati

Architettura e servizi Internet

Reti di Calcolatori - Laboratorio. Lezione 7. Gennaro Oliva

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

Gestione dei processi

Livello di Trasporto

Esercitazione [5] Input/Output su Socket

Applicazione Client-Server con Server Concorrente Specifiche

LIBRERIA SOCKET EFUNZIONI DI NETWORKING. Versione 1.0

Chiamate di sistema per la Gestione dei processi in POSIX. E.Mumolo, DEEI

AXO. Operativo. Architetture dei Calcolatori e Sistema. programmazione di sistema

Esercizio sulla gestione di file in Unix

Sistemi Operativi II Corso di Laurea in Ingegneria Informatica

Socket. [Pagina intenzionalmente vuota] 2: Socket ( ) slide 2:1/50 (p.24)

Introduzione alle applicazioni di rete

Opzioni per le Socket

Struttura degli indirizzi dei socket

Processi in Linux. Stru/ura file eseguibili

Una prima applicazione in C per l utilizzo delle socket

IPC System V. Code di messaggi

Programmazione multiprocesso

Processi e Sincronizzazione. Laboratorio Software C. Brandolese M. Grotto

Il sistema operativo LINUX Indice

Guida di Beej alla Programmazione di Rete

I file Laboratorio di Linguaggi di Programmazione a.a. 2001/2002

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

IL CONCETTO DI FILE. È illecito operare oltre la fine del file.

Le system call: fork(), wait(), exit()

Processi UNIX. I Processi nel SO UNIX. Gerarchie di processi UNIX. Modello di processo in UNIX

UDP. Livello di Trasporto. Demultiplexing dei Messaggi. Esempio di Demultiplexing

Basic Sniffer Tutorial

Uso di sniffer ed intercettazione del traffico IP

P2-11: BOOTP e DHCP (Capitolo 23)

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

Corso di Reti di Calcolatori

Corso di Reti di Calcolatori. Datagrammi

Controllo Winsock di Visual Basic

Sistemi Operativi: Programmazione di Sistema

Chiamate di sistema per la Inter Process Communication (IPC) in POSIX. E.Mumolo, DEEI

Il livello di Trasporto del TCP/IP

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

Transcript:

Autunno 2002 Prof. Roberto De Prisco -02: Socket TCP Università degli studi di Salerno Laurea e Diploma in Informatica Socket 02.2 Letteralmente significa presa (di corrente) È l astrazione di un canale di comunicazione fra due computer connessi da una rete Sono definiti per vari protocolli Per TCP/IP un socket identifica i due punti della connessione Un indirizzo IP ed una porta su un host Un indirizzo IP ed una porta sull altro host 1

Funzioni per i socket 02.3 Tipica interazione in una connessione TCP socket() bind() listen() CLIENT socket() connect() write() read() Stabilisce una connessione Dati (richiesta) Dati (risposta) accept() read() write() Aspetta una connessione SERVER close() Notificazione di fine comunicazione read() close() Sockaddr_in 02.4 struct in_addr { in_addr_t s_addr; /* 32-bit, network byte ordered */ struct sockaddr_in { uint8_t sin_len; sa_family_t sin_family; /* tipo di protocollo, AF_INET */ in_port_t sin_port; /* 16-bit, network byte ordered */ struct in_addr sin_addr; /* struttura indirizzo IP */ char sin_zero[8]; struct sockaddr { uint8_t sin_len; sa_family_t sin_family; /* tipo di protocollo: AF_XXX */ char sa_data[14]; /* indirizzo specifico del protocollo */ sin_zero Utilizzata per far si che la grandezza della struttura sia almeno 16 byte sin_len Non è richiesta dallo standard Posix Esistono diverse strutture con grandezze differenti 2

Lunghezze strutture socket 02.5 Funzione socket 02.6 #include <sys/socket.h> int socket(int family, int type, int protocol ); Valore di ritorno: -1 se errore un socket descriptor se OK Socket descriptor è come un file descriptor Sono presi dallo stesso insieme Se un intero è usato come file descriptor non può essere usato come socket descriptor e viceversa Socket e file sono visti più o meno allo stesso modo read, write, close sono le stesse funzioni dei file 3

Funzione socket int family Un intero che specifica quale famiglia di protocolli si intende usare: AF_INET IPv4 AF_INET6 IPv6 AF_LOCAL prot. locale (client e server sullo stesso host) AF_ROUTE Sockets per routing altri int type Un intero che dice il tipo di socket SOCK_STREAM per uno stream di dati (TCP) SOCK_DGRAM per datagrammi (UDP) SOCK_RAW per applicazioni dirette su IP int protocol 0, tranne che per SOCK_RAW 02.7 Funzione connect 02.8 #include <sys/socket.h> int connect(int sd, struct sockaddr *servaddr, socklen_t addrlen); Valore di ritorno: -1 se errore, 0 se OK Permette ad un client di aprire una connessione con il server Il kernel sceglie una porta effimera (e l indirizzo IP) Nel caso di una connessione TCP viene fatto l handshaking, in caso di errore ritorna ETIMEDOUT ECONNREFUSED EHOSTUNREACH 4

Funzione bind 02.9 #include <sys/socket.h> int bind(int sd, struct sockaddr*myaddr, socklen_t addrlen); Valore di ritorno: -1 se errore, 0 se OK Permette ad un server di assegnare un indirizzo per il server al socket Con TCP l indirizzo può essere indirizzo IP (deve essere una delle interfacce) porta entrambi nessuno Se la porta non è specificata (valore 0) ne viene scelta una effimera Se l indirizzo IP è quello wildcard (INADDR_ANY, 0) viene usato quello designato come IP destinazione nel SYN del client Funzione listen 02.10 #include <sys/socket.h> int listen(int sd, int backlog); Valore di ritorno: -1 se errore, 0 se OK Usata solo da un server TCP, serve a 1. Convertire il socket da attivo a passivo, per far sì che il kernel accetti connessioni sul socket Per default un socket è creato attivo, e il kernel si aspetta che sia il socket di un client Nel diagramma a stati TCP fa muovere da CLOSED a LISTEN 2. Backlog specifica quante connessioni accettare e mettere in attesa per essere servite 5

Backlog 02.11 Server accept CODA connessioni completate (stato ESTABLISHED) apertura conn. completata CODA connessioni incomplete (stato SYN_RCVD) connect dal client SYN apertura connessione La somma degli elementi in entrambe le code non può superare il backlog Funzione accept 02.12 #include <sys/socket.h> int accept(int sd, struct sockaddr*cliaddr, socklen_t addrlen); Valore di ritorno: -1 se errore, socked descriptor se OK Permette ad un server di prendere la prima connessione completata dalla coda Se non ce ne sono si blocca cliaddr è un parametro valore-risultato In chiamata contiene il listening socket Al ritorno contiene il socket connesso al particolare client 6

Daytime server (1) 02.13 #include "basic.h" #include <time.h> int main(int argc, char **argv) { pid_t pid; int listenfd, connfd; struct sockaddr_in servaddr; char buff[maxline]; time_t ticks; struct servent *sp; if( (listenfd = socket(af_inet, SOCK_STREAM, 0)) < 0) err_sys("socket error"); daytimesrv.c if( (sp = getservbyname("daytime", "tcp")) == NULL ) { fprintf(stderr, "getservbyname error for daytime, tcp."); exit(-1); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(inaddr_any); servaddr.sin_port = sp->s_port; if( (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr))) < 0) err_sys("bind error"); if( listen(listenfd, BACKLOG) < 0 ) /* backlog = 5 */ err_sys("listen error"); Daytime server (2) 02.14 for ( ; ; ) { if( (connfd = accept(listenfd, (struct sockaddr *) NULL, NULL)) < 0) err_sys("accept error"); ticks = time(null); snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks)); write(connfd, buff, strlen(buff)); close(connfd); Server iterativo Serve i client uno alla volta Quando un client è connesso il seguente client deve aspettare Accettabile per server semplici come il daytime 7

Daytime client (1) 02.15 #include "basic.h" int main(int argc, char **argv) { int sockfd, n; char recvline[maxline + 1]; struct sockaddr_in servaddr; struct in_addr **pptr; struct hostent *hp; struct servent *sp; daytimecli.c if (argc!= 3) err_quit("usage: daytimecli <hostname> <service>"); if ( (hp = gethostbyname(argv[1])) == NULL) err_quit("hostname error for %s: %s", argv[1], hstrerror(h_errno)); if ( (sp = getservbyname(argv[2], "tcp")) == NULL) err_quit("getservbyname error for %s", argv[2]); pptr = (struct in_addr **) hp->h_addr_list; Daytime client (2) 02.16 for ( ; *pptr!= NULL; pptr++) { if( (sockfd = socket(af_inet, SOCK_STREAM, 0)) < 0 ) err_sys("socket error"); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = sp->s_port; memcpy(&servaddr.sin_addr, *pptr, sizeof(struct in_addr)); if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) == 0) break; /* success */ err_ret("connect error"); close(sockfd); if (*pptr == NULL) err_quit("unable to connect"); while ( (n = read(sockfd, recvline, MAXLINE)) > 0) { recvline[n] = 0; /* null terminate */ fputs(recvline, stdout); exit(0); 8

Server ricorsivi 02.17 Un server ricorsivo usa una copia di se stesso per servire una richiesta pid_t int pid; listenfd, connfd; listenfd = socket(.); /* riempi la struttura sockaddr_in (es. numero di porta) */ bind(listenfd,.) listen(listenfd, LISTENQ) for ( ; ; ) { connfd = accept(listenfd, ); if ( (pid = fork()) == 0) { close(listenfd); /* figlio chiude il socket di ascolto */ DOIT(connfd); /* serve la richiesta */ close(connfd); /* chiude il socket */ exit(0); /* il figlio termina */ close(connfd); /* il padre chiude il socket della connessione */ Server ricorsivi 02.18 Client connect() Richiesta di connessione Server listensd Il server chiama accept() Viene creato un nuovo socket descriptor nel server per la connessione con questo particolare client Client connect() Connessione stabilita Server listensd connsd 9

Server ricorsivi 02.19 Client connect() Connessione stabilita Server listensd connsd padre Server listensd connsd figlio Il server chiama fork() Padre e figlio nel server condividono il socket Server ricorsivi 02.20 Client connect() Server listensd connsd padre Connessione stabilita Server listensd Il padre chiude il socket della connessione Può accettare nuove connessioni connsd figlio Il figlio chiude il socket per l accettazione di nuove connessioni Può gestire la connessione con il client 10

Getsockname e getpeername 02.21 #include <sys/socket.h> int getsockname(int sd, struct sockaddr*localaddr, socklen_t addrlen); int getpeername(int sd, struct sockaddr*remoteaddr, socklen_t addrlen); Valore di ritorno: -1 se errore, socked descriptor se OK Ritornano l indirizzo locale associato al socket L indirizzo dell altro lato della connessione associata al socket Serve perché Un client che non chiama bind non sa quale porta è stata usata Un client non sa l indirizzo IP usato se ci sono più interfaccie Una chiamata a bind con porta=0 assegna una porta effimera Stessa cosa per l indirizzo IP (INADDR_ANY) Dopo una exec si può risalire agli indirizzi della connessione NB: un file descriptor rimane aperto quando si chiama exec Echo server (1) 02.22 #include #include "basic.h" "echo.h" echosrv.c int main(int argc, char **argv) { pid_t childpid; int listenfd, connfd; struct sockaddr_in servaddr, cliaddr; socklen_t cliaddr_len; if( (listenfd = socket(af_inet, SOCK_STREAM, 0)) < 0) err_sys("socket error"); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(inaddr_any); servaddr.sin_port = htons(port); /* daytime server */ if( (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr))) < 0) err_sys("bind error"); if( listen(listenfd, LISTENQ) < 0 ) err_sys("listen error"); 11

Echo server (2) 02.23 for ( ; ; ) { cliaddr_len = sizeof(cliaddr); if( (connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &cliaddr_len)) < 0) err_sys("accept error"); if( (childpid = fork()) == 0 ) { close(listenfd); str_echo(connfd); exit(0); close(connfd); void str_echo(int sockfd) { ssize_t n; char line[maxline]; for ( ; ; ) { if ( (n = read(sockfd, line, MAXLINE)) == 0) return; /* connection closed by other end */ write(sockfd, line, n); #include "basic.h" #include "echo.h" int main(int argc, char **argv) { int sockfd, n; struct sockaddr_in servaddr; Echo client (1) echocli.c 02.24 if (argc!= 2) err_quit("usage: echotcpcli <IPaddress>"); if ( (sockfd = socket(af_inet, SOCK_STREAM, 0)) < 0) err_sys("socket error"); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(port); /* echo server */ if (inet_pton(af_inet, argv[1], &servaddr.sin_addr) <= 0) err_quit("inet_pton error for %s", argv[1]); if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) err_sys("connect error"); str_cli(stdin, sockfd); /* svolge tutto il lavoro del client */ exit(0); 12

Echo client (2) 02.25 void str_cli(file *fp, int sockfd) { char sendline[maxline], recvline[maxline]; while (fgets(sendline, MAXLINE, fp)!= NULL) { reti_writen(sockfd, sendline, strlen(sendline)); if (reti_readline(sockfd, recvline, MAXLINE) == 0) err_quit("str_cli: server terminated prematurely"); fputs(recvline, stdout); Echo server 02.26 Per semplicità facciamo girare server e client sulla stessa macchina prompt > echoserver & [1] 21130 prompt > netstat a Proto Recv-Q Send-Q Local address Foreign address (state) Tcp 0 0 *.9877 *.* LISTEN prompt > echoclient 127.0.0.1 In un altra finestra prompt > netstat a Proto Recv-Q Send-Q Local address Foreign address (state) Tcp 0 0 localhost.9877 localhost.1052 ESTABLISHED Tcp 0 0 localhost.1052 localhost.9877 ESTABLISHED Tcp 0 0 *.9877 *.* LISTEN A questo punto la connessione è stabilita 13

Echo server 02.27 prompt > echoclient 127.0.0.1 Ciao server Ciao server Arrivederci Arrivederci ^D prompt > Digitata al terminale Risposta del server Digitata al terminale Risposta del server Digitata al terminale prompt > netstat a grep 9877 Tcp 0 0 localhost.1052 localhost.9877 TIME_WAIT Tcp 0 0 *.9877 *.* LISTEN Il server ha chiuso il socket Il client è nello stato di TIME_WAIT Il lato che chiude la connessione rimane in questo stato per un certo periodo (2MSL) per 1. Mantenere informazioni nel caso l ultimo ACK viene perso e l altro lato rispedisce l ultimo FIN 2. Permettere a vecchi pacchetti di essere eliminati dalla rete in modo da non farli interferire con successive connessioni Echo server 02.28 Digitando ^D, il client termina chiamando exit Il kernel chiude tutti i file descriptor, quindi anche i socket descriptor Quindi il socket del client viene chiuso La chiusura implica la spedizione di FIN al server La ricezione dell ACK al FIN A questo punto il server è nello stato CLOSE_WAIT mentre il client è nello stato FIN_WAIT_2 La prima parte della chiusura di una connessione TCP è conclusa Quando il server riceve il FIN è nella readline che ritorna EOF e quindi chiama exit I file descriptor vengono chiusi, quindi anche il socket ed un FIN viene spedito al client A questo punto la conessione è completamente terminata ed il client va nello stato TIME_WAIT mentre il server ha chiuso la connessione Dopo un certo periodo (2 Maximum Segment Lifetime) il client chiude la connessione 14

Segnale SIGCHLD 02.29 In un server ricorsivo, il server crea un figlio per gestire la connessione quando la connessione viene chiusa il figlio termina Il sistema operativo manda un segnale di SIGCHLD al padre e il figlio diventa zombie Zombie sono dei processi terminati per i quali vengono mantenuti dei dati nel sistema operativo Zombie sono necessari per permettere al padre di controllare il valore di uscita del processo e utilizzo delle risorse del figlio (memoria, CPU, etc.) Ovviamente non vogliamo lasciare zombie Occorre scrivere un signal handler che chiama wait zombie 02.30 Ognli client che termina lascia uno zombie <defunct> indica uno zombie robdep@zaffiro:~/corsi/reti/c> echocli 127.0.0.1 ciao ciao ^D robdep@zaffiro:~/corsi/reti/c> echocli 127.0.0.1 pippo pippo ^D robdep@zaffiro:~/corsi/reti/c> ps PID TTY TIME CMD 1077 pts/0 00:00:00 cat 22084 pts/2 00:00:00 bash 27162 pts/3 00:00:00 ssh 30007 pts/6 00:00:00 bash 30331 pts/11 00:00:00 bash 30761 pts/11 00:00:00 echosrv 30765 pts/11 00:00:00 echosrv <defunct> 30767 pts/11 00:00:00 echosrv <defunct> 30768 pts/6 00:00:00 ps Il client viene ucciso Il client viene ucciso 15

Signal handler 02.31 void sig_child(int signo) { pid_t pid; int stat; while ( pid = waitpid(-1,&stat,wnohang)) > 0) { printf( Child %d terminated\n,pid); Utilizzando il gestore di segnali si evitano i processi zombie Appena il figlio finisce viene chiamata waitpid Prompt > echoserver & [2] 19287 prompt > echoclient 127.0.0.1 Ciao server Ciao server ^D Child 19293 terminated accept error: interrupted system call Interruzione delle system call 02.32 Il segnale è stato catturato dal padre durante l esecuzione di accept Il gestore del segnale viene eseguito Poiché è stata interrotta la funzione accept ritorna con il codice di errore EINTR Poiché la gestione di tale errore non è prevista il server termina l esecuzione Occorre tener presente questo problema In alcuni sistemi le system call sono automaticamente richiamate in altri no 16

Una possibile soluzione 02.33 for ( ; ; ) { clilen = sizeof(cliaddr); if ( (connfd = accept(listenfd, &cliaddr, &clilen)) < 0) { if (errno = EINTR) continue; else { perror( accept error ); exit(1); Se la chiamata ad accept ritorna EINTR accept viene richiamata Se l errore è diverso da EINTR Si gestisce l errore (nell esempio si chiama exit) Reset connessione e accept 02.34 Un altro errore tipico da gestire con accept è il reset della connessione prima della chiamata ad accept La connessione diventa ESTABLISHED Il client spedisce un RST Il server chiama accept Accept ritorna un codice di errore ECONNABORTED Il server può richiamare accept per la prossima connessione 17

Terminazione del server 02.35 Cosa succede se il server termina prematuramente? Prompt > echoclient 127.0.0.1 Ciao Ciao Il server viene ucciso Arrivederci Il server non risponde (dipende dal codice) Al kill i socket descriptor vengono chiusi Un FIN viene spedito al client Il client spedisce Arrivederci al server È permesso perché il client non ha chiuso il socket Il client chiama readline che ritorna EOF Non si aspetta di ricevere EOF quindi stampa il messaggio di errore e termina SIGPIPE 02.36 Cosa succede se il client ignora l errore su readline e scrive nel socket? Questo può capitare se il codice ha due write consecutive La prima fa sì che il server spedisca RST La seconda crea il problema Viene generato un segnale di SIGPIPE Il processo termina se il segnale non viene catturato o ignorato Se SIGPIPE è ignorato l operazione di write genera l errore di EPIPE Soluzione semplice, quando non si deve reagire all errore 1. Ignorare (SIG_IGN) il segnale di SIGPIPE Assume che non occorre fare niente di speciale in tale circostanza 2. Controllare l errore di EPIPE sulle write e nel caso di errore terminare (non scrivere più) 18

Macchina server non raggiungibile 02.37 Un altra possibile causa di errore è se la macchina server non risponde proprio Diverso da uccidere il processo server (in quel caso vengono spediti FIN, RST) Può dipendere dalla rete O dalla macchina server Il client è bloccato in readline TCP ritrasmetterà i dati per ricevere l ACK fino ad un certo timeout La funzione di lettura dal socket ritorna un errore ETIMEOUT EHOSTUNREACH, ENETUNREACH Server shutdown and reboot 02.38 La connessione viene stabilita Il server va giù e fa il reboot senza che il client se ne accorga Non c è comunicazione durante lo shutdown (server scollegato dalla rete altrimenti spedisce FIN) Il client spedisce nuovi dati al server dopo il reboot Il server non ha più il socket aperto TCP risponde ai dati con un RST Client è in readline quando riceve RST Readline ritorna ECONNRESET 19

Server somma 02.39 Solo la funziona che gestisce il client void server_somma(int sockfd) { int i, arg1, arg2; ssize_t n; char sendline[maxline], rcvline[maxline]; char c; for ( ; ; ) { if ( (n = reti_readline(sockfd, rcvline, MAXLINE)) == 0) return; /* connection closed by other end */ /* legge dalla stringa passata dal client i due interi da sommare */ if( sscanf(rcvline, "%d %d", &arg1, &arg2) == 2 ) /* converte il risultato in stringa e lo scrive nel buffer */ sprintf(sendline, "%d\n", arg1 + arg2); else sprintf(sendline, "input error\n"); n = strlen(sendline); reti_writen(sockfd, sendline, n); sommasrv.c Client somma 02.40 Il codice del client somma è un pò più complesso Deve gestire due input I dati in arrivo dal socket I dati digitati dall utente alla tastiera Questo problema verrà affrontato in seguito IO multiplexing Select Il codice è disponibile sulla pagina Web sommacli.c 20

Problema 02.41 Client e server, stesso tipo di macchina sunos5 > sommacli 206.62.226.33 11 22 33-11 -44-55 Client e server, macchine di tipo diverso Una Sparc l altra Intel bsdi > sommacli 206.62.226.33 11 22 33-11 -44-16542537 Sparc: big-endian, Intel: little-endian 21