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



Documenti analoghi
Socket TCP. prima parte

CORSO DI SISTEMI OPERATIVI A - ESERCITAZIONE 6

COMUNICAZIONE TRA PROCESSI REMOTI IN UNIX

Socket TCP. seconda parte

Esercitazione [6] Client/Server con Socket

Esempio 1: stampa locale di file remoto

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

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

I Socket. Laboratorio Software M. Grotto R. Farina

(VHUFLWD]LRQLGLEDVHVXOOH6RFNHWLQ&

Interazione (TCP) Client-Server con le socket

Cenni di programmazione distribuita in C++ Mauro Piccolo

rsystem Maximiliano Marchesi

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

Laboratorio di Sistemi Operativi Cognome Nome Mat.

Una semplice applicazione client/server 1

IPC Inter Process Communication

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

Esercizio 2. Client e server comunicano attraverso socket TCP

I/O su Socket TCP: read()

unsigned long inet_addr(cp) char *cp;

Esercitazioni Socket

Esercitazione [08] Server multi-process/multi-thread

Esercitazione Laboratorio di Sistemi Operativi Cognome Nome Mat.

Esercitazione [7] Server multi-process/multi-thread

Interazione (TCP) Client-Server con le socket

*HVWLRQHDYDQ]DWDGHOOH6RFNHWLQ& ODSULPLWLYDVHOHFW

Program m azione di Sistem a 6

Scrittura dei programmi applicativi di rete

INTERNET DOMAIN SOCKETS (Cap.59)

Introduzione ai socket

Programmazione di Rete

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

Laboratorio di Reti di Calcolatori

Esercitazione [7] Client/Server con Socket

Programmazione socket. Queste slide sono distribuite con licenza Creative Commons Attribuzione-Non commerciale-condividi allo stesso modo 2.

Creare una applicazione Winsock di base

Reti (già Reti di Calcolatori )

LABORATORIO di Reti di Calcolatori

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

DATAGRAM SOCKET. Angelastro Sergio Diomede Antonio Viterbo Tommaso

Corso di Sistemi Operativi Esercitazioni

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

RETI DI CALCOLATORI. Prof. PIER LUCA MONTESSORO Ing. DAVIDE PIERATTONI. Facoltà di Ingegneria Università degli Studi di Udine

Il client deve stampare tutti gli eventuali errori che si possono verificare durante l esecuzione.

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

Socket per TCP: Fondamenti

Laboratorio reti AA 2008/2009. Dott. Matteo Roffilli Ricevimento in ufficio dopo la lezione

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

1. RETI INFORMATICHE CORSO DI LAUREA IN INGEGNERIA INFORMATICA SPECIFICHE DI PROGETTO A.A. 2013/ Lato client

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

Esercitazione [5] Input/Output su Socket

Laboratorio di Reti di Calcolatori

L interfaccia socket

Progettazione di un client TCP. Progettazione di un server TCP. Esempio: daytime TCP. Client TCP daytime

Scrittura dei programmi applicativi di rete

SCUOLA DI INGEGNERIA DELL INFORMAZIONE. Corso di Piattaforme Software per la rete MODULO 2 Anno Accademico Prof. William FORNACIARI

Creare un'elementare backdoor in C in ambiente UNIX

Programmazione dei socket con TCP #2

Laboratorio di. Reti Informatiche. Corso di Laurea Triennale in Ingegneria Informatica A.A. 2016/2017. Ing. Niccolò Iardella

Corso di Reti di Calcolatori T

Parte II: Reti di calcolatori Lezione 12

Sistemi di Elaborazione. Introduzione alla Programmazione distribuita

Interprocess Communications - II. Franco Maria Nardini

Luca Mari, Sistemi informativi applicati (reti di calcolatori) appunti delle lezioni. Architetture client/server: applicazioni client

Esercitazione [8] Pipe e FIFO

Paradigma client-server

Internetworking with TCP/IP (Douglas E. Comer) Vol. I and Vol III.

Laboratorio di Programmazione in rete

C UDP in Windows p53 - variante 1

Introduzione alle applicazioni di rete

Il protocollo applicativo. Esempio di protocollo applicativo

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

Applicazioni distribuite. La programmazione di rete. Interfacce e protocolli. Protocollo applicativo

Esempio 1: stampa locale di file remoto

IPC System V. Code di messaggi

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

La programmazione di rete

Parte II: Reti di calcolatori Lezione 10

Laboratorio reti AA 2007/2008. Dott. Matteo Roffilli Ricevimento in ufficio dopo la lezione

5 Esercitazione (svolta):

Inter-process communication: socket

MODELLO CLIENT/SERVER. Gianluca Daino Dipartimento di Ingegneria dell Informazione Università degli Studi di Siena

Laboratorio reti AA 2008/2009. Dott. Matteo Roffilli Ricevimento in ufficio dopo la lezione

HTTP adaptation layer per generico protocollo di scambio dati

programmazione distribuita Introduzione Introduzione alla programmazione distribuita

Gestione dei File in C

Laboratorio reti AA 2008/2009. Dott. Matteo Roffilli Ricevimento in ufficio dopo la lezione

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

Sistemi Operativi (M. Cesati)

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

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

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

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

Comunicazione Connectionless o Datagram

Esercizio 1. Esercizio 1

Laboratorio di Programmazione in Rete

Transcript:

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

Sommario Comunicazione tra processi su macchine diverse in rete: Socket TCP o Socket Stream Esercizi: Socket TCP Client/Server Interattivo Client/Server Interattivo trasferire file con socket Gestire più client: Client/Server Concorrente multi-processo Client/Server Concorrente multi-thread 2

- Socket TCP o Socket Stream - 3

- Socket TCP: Generalità Canale di comunicazione bidirezionale tra processi attivi su nodi diversi della stessa rete. Creata all interno del dominio internet in cui viene utilizzato protocollo TCP per lo scambio di dati tra i vari nodi. il NODO: INDIRIZZO IP PROCESSO A NODO: INDIRIZZO IP PROCESSO B socket porta Internet (TCP/IP) porta socket 4

- Socket TCP: Dominio & Indirizzi Il dominio all interno del quale viene creata la socket TCP si chiama dominio internet e lo si rappresenta: con il protocollo family PF_INET oppure addres family AF_INET (dominio internet) In questo dominio, ogni nodo è identificato da: numero di porta ( 2 byte = intero a 16 bit da 0 a 65535 ) indirizzo IP (4 byte = intero a 32 bit es. 143.225.5.3) che rappresentano il formato degli indirizzi internet. Quindi, si deve utilizzare una struttura con cui rappresentare tipi di indirizzo. questo 5

- Socket TCP: Formato degli Indirizzi Ipv4 #include <netinet/ip.h> struct sockaddr_in { short sa_family; /* Famiglia di indirizzi AF_INET */ short sin_port; /* Numero di porta 2 byte*/ struct in_addr sin_addr; /* indir. IP 4 byte*/ char sin_zero[8]; /* riempimento non usato */ }; dovein_addr rappresenta un indirizzo IP struct in_addr { u_long s_addr; /* 4 byte */ }; 6

- Socket TCP: Struttura Indirizzi Ipv4 Il membro sin_family deve essere sempre impostato (2 byte) sin port specifica il numero di porta (2 byte) Il membro sin_addr contiene l indirizzo internet del destinatario comunicazione. (4 byte) della sin_zero (8 byte) serve a far si che la grandezza della struttura sia almeno 16 byte. (riempimento) 7

- Socket TCP: Struttura Indirizzi Ipv4 Nel protocollo TCP/IP, gli interi cioè gli indirizzi e i numeri di porta sono trasmessi in network byte order ossia: byte ordinati in formato big endian (prima il byte più significativo) Sono necessarie apposite funzioni di conversione per mantenere la portabilità del codice. Infatti, i processori memorizzano interi in memoria sia in formato big endian (Motorola) che little endian (Pentium) (prima byte meno significativo) Funzioni di conversione tra interi a 16 e 32 senza segno unsigned: #include <netinet/in.h> 1. uint32_t htonl(uint32_t x) (big endian) 2. uint16_t htons(uint16_t x) Returns: Valore in network byte order 1. uint32_t ntohl(uint32_t x) 2. uint16_t ntohs(uint16_t x) Returns: Valore in host byte order 8

- Socket TCP: Conversione indirizzi IP Funzione inet_aton (ascii to network): Ipv4 #include <netinet/in.h> struct sockaddr_in indirizzo; if (inet_aton( 143.225.5.3, &indirizzo.sin_addr) == 0) perror( inet_aton ), exit(1); converte l indirizzo IP (usando la notazione puntata) in un unsigned long mette nel campo sin_addr della struttura degli indirizzi Restituisce: zero in caso di errore l indirizzo in Network byte Order altrimenti e lo 9

- Socket TCP: Conversione indirizzi IP Funzione inet_ntop: Ipv6 #include <netinet/in.h> char buff[maxline]; struct sockaddr_in cliaddr; if(inet_ntop(af_inet,&cliaddr.sin_addr,buff,sizeof(buff))== 0) perror( inet_ntop ), exit(1); Converte l indirizzo dalla relativa struttura in una stringa simbolica Restituisce: NULL in caso di errore un puntatore non nullo alla stringa convertita in caso si successo 10

- Socket TCP: Impostare indirizzi 11

- Socket TCP: Funzione bind (lato server) Permette di assegnare uno specifico indirizzo al socket: struct sockaddr_in mio_indirizzo; mio_indirizzo.sin_family = AF_INET; mio_indirizzo.sin_port = htons(5200); mio_indirizzo.sin_addr.s_addr = htonl(inaddr_any); bind(fd, (struct sockaddr *) &mio_indirizzo, sizeof(mio_indirizzo)); Il server chiama bind per stabilire su quale indirizzo mettersi in ascolto Solitamente si scegli solo il numero di porta Come indirizzo IP, sceglie INADDR_ANY, cosi' accetta connessioni dirette a qualunque indirizzo 12

- Socket TCP: Funzione connect (lato client) Permette ad un client di aprire una connessione con il server: Il client deve conoscere l'indirizzo IP e la porta del processo server struct sockaddr_in indirizzo; indirizzo.sin_family = AF_INET; indirizzo.sin_port = htons(5200); inet_aton( 143.225.5.3, &indirizzo.sin_addr); Accetta connessioni solo dall indirizzo ip specificato 143.225.5.3 connect(fd, (struct sockaddr *) &indirizzo, sizeof(indirizzo)); La funzione termina solo dopo che la connessione è stata creata Restituisce: 0 se ok -1 in caso di errore 13

- Socket TCP: Funzione gethostbyname (lato client) Ottenere un indirizzo IP a partire dal nome di un host #include <sys/socket.h> #include <netdb.h> struct hostent *gethostbyname(const char *name); Restituisce: un puntatore a struttura di tipo hostent che tra le tante informazioni contiene anche l indirizzo IP NULL in caso di errore 14

- Socket TCP: Struttura di un server Esempio: int fd1, fd2; struct sockaddr_in mio_indirizzo; mio_indirizzo.sin_family = AF_INET; mio_indirizzo.sin_port = htons(5200); mio_indirizzo.sin_addr.s_addr = htonl(inaddr_any); fd1 = socket(pf_inet, SOCK_STREAM, 0); Accetta connessioni dirette qualunque indirizzo a bind(fd1, (struct sockaddr *) &mio_indirizzo, sizeof(mio_indirizzo)); listen(fd1, 5); fd2 = accept(fd1, NULL, NULL);... close(fd2); close(fd1); 15

- Socket TCP: Struttura di un client Esempio: int fd, portno; struct sockaddr_in serv_addr; struct hostent *server; server = gethostbyname(argv[1]); portno = atoi(argv[2]); fd = socket(pf_inet, SOCK_STREAM, 0); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(portno); memcpy((char *)&serv_addr.sin_addr,(char *)server->h_addr, server->h_length); connect(fd,(struct sockaddr *) & serv_addr, sizeof(serv_addr));... close(fd); 16

Vengono scambiati tra client e server tre segmenti prima di instaurare una connessione (SYN1/SYN2-ACK1/ACK2) 17

- Esercizio: client/server con socket TCP e server interattivo - 18

Esercizio n 1 Socket TCP Realizzare uno scambio di messaggi tra client e server mediante socket TCP. Il client invia un messaggio al server, il quale dopo aver ricevuto il messaggio comunica al client l avvenuta ricezione. Utilizzo, lanciare i due programmi in due shell separate della stessa macchina o di macchine diverse Esecuzione sulla stessa macchina $./server.out <numero_porta> $./client.out localhost <numero_porta> Utilizzare come <numero_porta> il numero di matricola Esecuzione sul macchine diverse $./server.out <numero_porta> $./client.out IP macchina server <numero_porta> Output: (CLIENT) Scrivere un messaggio: ciao (SERVER) Ecco il messaggio ricevuto dal client: ciao (CLIENT) Ecco il messaggio ricevuto dal server: MESSAGGIO RICEVUTO, FINE COMUNICAZIONE N.B. localhost è il nome della macchina su cui è lanciato il processo server 19

Sol. Eser. n 1 server.c #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> void error(char *msg) { perror(msg); exit(1);} int main(int argc, char *argv[]) { int sockfd, newsockfd, portno; char buffer[256]=""; struct sockaddr_in serv_addr; int n; char *messaggio_ricevuto="messaggio RICEVUTO, FINE COMUNICAZIONE"; if (argc < 2) { fprintf(stderr,"errore, nessuna porta specificata\n"); exit(1); } 20

Sol. Eser. n 1 server.c sockfd = socket(af_inet, SOCK_STREAM, 0); if (sockfd < 0) error("errore DI APERTURA DELLA SOCKET"); portno = atoi(argv[1]); Accetta connessioni dirette qualunque indirizzo serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); //return network byte order a if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) error("errore DI BINDING"); listen(sockfd,5); 21

Sol. Eser. n 1 server.c while((newsockfd = accept(sockfd, NULL, NULL)) > -1) { if (newsockfd < 0) error("errore DI ACCEPT"); n = read(newsockfd, buffer, 255); if (n < 0) error("errore in lettura dalla socket"); printf("(server) Messaggio ricevuto dal client: %s\n",buffer); n = write(newsockfd,messaggio_ricevuto,strlen(messaggio_ricevuto)+1); if (n < 0) error("errore in scrittura sulla socket"); close(sockfd); }//end while close(newsockfd); return 0; } //end server 22

Sol. Eser. n 1 client.c #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <string.h> void error(char *msg) {perror(msg); exit(0);} int main(int argc, char *argv[]) {int sockfd, portno, n; struct sockaddr_in serv_addr; struct hostent *server; char send_buffer[256]; char rec_buffer[256]=""; if (argc < 3) { fprintf(stderr,"uso %s nomehost porta\n", argv[0]); exit(0);} 23

portno = atoi(argv[2]); Sol. Eser. n 1 client.c sockfd = socket(af_inet, SOCK_STREAM, 0); if (sockfd < 0) error("errore in apertura"); server = gethostbyname(argv[1]); if (server == NULL) { fprintf(stderr,"errore, l host non esiste\n"); exit(0); } serv_addr.sin_family = AF_INET; memcpy((char *)&serv_addr.sin_addr,(char *)server->h_addr, server->h_length); serv_addr.sin_port = htons(portno); if (connect(sockfd,(struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) error("errore di connessione"); 24

Sol. Eser. n 1 client.c printf("(client) Scrivere un messaggio: "); fgets(send_buffer,255,stdin);/*legge una linea dallo standard output*/ n = write(sockfd,send_buffer,strlen(send_buffer)); if (n < 0) error("errore in scrittura sulla socket"); n = read(sockfd,rec_buffer,255); if (n < 0) error("errore in lettura sulla socket"); printf("(client) Mess ricevuto dal server: %s\n",rec_buffer); close(sockfd); return 0; }//end client 25

- Esercizio: client/server con socket TCP Server concorrente multi processo - 26

Esercizio n 2 Socket TCP Scrivere due programmi C, server.c e client.c. che comunicano tramite socket TCP. Il server.c crea una socket TCP, ed ogni volta che instaura una connessione con un client, mediate fork crea un nuovo processo (server concorrente) e stampa a video l indirizzo IP del client che ha effettuato la connessione. Tale processo, dovrà leggere sul socket il messaggio scritto dal client stampandolo a video (lanciare l esecuzione dei due programmi su due shell distinti della stessa macchina o di macchine diverse) Esecuzione di processi sulla stessa macchina $ (shell1)./server.out <numero_porta> $ (shell2)./client.out localhost <numero_porta> Esecuzione di processi su macchine diverse $ (shell1)./server.out <numero_porta> $ (shell2)./client.out IP macchina server <numero_porta> Si utilizzi fgets per il messaggio da riga di comando 27

Sol. Eser. n 2 server.c #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <netdb.h> #include <stdlib.h> main(int argc, char *argv[]) {int s, ns, pid,portno; struct sockaddr_in sin, client; char buf[80], char buffer[80]; if ((s = socket(af_inet, SOCK_STREAM, 0)) == -1) {perror("errore: socket"); exit(1); } portno = atoi(argv[1]); sin.sin_family = AF_INET; sin.sin_port = htons(portno); sin.sin_addr.s_addr = htonl(inaddr_any); if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { perror("errore: bind"); exit(1); } if (listen(s, 5) == -1) { perror("errore: listen"); exit(1); } 28

len=sizeof(client); while(1) //loop infinito {if ((ns = accept(s,(struct sockaddr *)&client,&len)) == -1) { perror("errore: accept"); exit(1); } if ((pid = fork()) == -1) { Sol. Esercizio N 2 server perror("errore: fork"); exit(1); } if (pid == 0) { while(1) { if ((pid = read(ns, buf, sizeof(buf))) == -1) { perror("tomd: read"); exit(1); } if (pid < sizeof(buf)) break; printf("messaggio da client: %s", buf); } close(ns);//il figlio termina exit(0); } //end if inet_ntop(af_inet, &client.sin_addr, buffer, sizeof(buffer)); printf("request from host %s\n", buffer); close(ns); }//end loop}//end server 29

Sol. Eser. n 2 client.c #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <string.h> main(int argc,char *argv[]){ int s,portno; struct sockaddr_in sin; struct hostent *hp; char buf[80]; if (argc!= 3) { printf("illegal number of arguments"); exit(1); } if ((hp = gethostbyname(argv[1])) == 0) { perror("tom: gethostbyname"); exit(1); } 30

Sol. Eser. n 2 client.c portno = atoi(argv[2]); sin.sin_family = AF_INET; memcpy((char *)&sin.sin_addr,(char *)hp->h_addr,hp->h_length); sin.sin_port = htons(portno); if ((s = socket(af_inet, SOCK_STREAM, 0)) == -1) { perror( errore: socket"); exit(1); } if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { perror( errore: connect"); exit(1);} printf("(client) Scrivere un messaggio: "); fgets(buf,255,stdin); if (write(s, buf, sizeof(buf)) == -1) { perror( errore: write"); exit(1); } close(s); } 31

- Esercizio: client/server con socket TCP Server concorrente multi-thread per gestire più client- 32

Esercizio n 3 Socket TCP Scrivere due programmi C, servermultithread.c e client.c. Il programma servermultithread.c, crea una socket TCP e rimane in attesa di ricevere una connessione. Quando riceve una connessione, crea un thread con chiamata ad una funzione che gestisce la connessione, mentre il programma server rimane in ascolto per eventuali altre richieste di connessione. Il programma client, si connette alla socket TCP ed invia il messaggio passato da tastiera (usare fgets) al server. Il server dopo aver stampato l indirizzo IP del client connesso tramite il thread legge il messaggio e lo stampa a video (Lanciare i due programmi in due shell distinte della stessa macchina o di macchine diverse, e compilare il server con -lpthread) Esecuzione server: $./servermultithread.out <numporta> Esecuzione client: $./client.out localhost e/o IP macchina server <numporta> 33

- Comunicazione client/server con socket TCP - Schema Server concorrente multi-thread per gestire più client server Socket TCP client 1 pthread_create() processo thread legge il messaggio del client dalla socket gestisci Il processo thread gestisce la connessione con i client stampa il messaggio del client a video 34

- Comunicazione client/server con socket TCP - Schema Server concorrente multi-thread per gestire più client server client 1 127.0.0.1 Thread_1 Connesso a 127.0.0.1 Connesso a 192.168.1.1 Thread_2 client 2 192.168.1.1 35

#include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <pthread.h> #include <netinet/in.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #define N 256 Sol. Eser. n 3 server.c void *gestisci(void *arg) { printf("gestisci(): creato il thread\n"); char buf[n]; while (read((int *) arg, buf, N)!= 0) { printf("server %s\n", buf); } close((int *) arg); pthread_exit (0); } 36

Sol. Eser. n 3 server.c int main(int argc, char *argv[]) { int s_fd, c_fd, portno, len; pthread_t tid; char buffer[n]; struct sockaddr_in sin, client; s_fd = socket(af_inet, SOCK_STREAM, 0); portno = atoi(argv[1]); sin.sin_family = AF_INET; sin.sin_port = htons(portno); sin.sin_addr.s_addr = htonl(inaddr_any); len = sizeof(client); bind(s_fd, (struct sockaddr *) &sin, sizeof(sin)); isten(s_fd, 5); 37

Sol. Eser. n 3 server.c while (1) { c_fd = accept(s_fd, (struct sockaddr *)&client, &len); inet_ntop(af_inet, &client.sin_addr, buffer, sizeof(buffer)); printf("request from client %s\n", buffer); } pthread_create(&tid, NULL, gestisci, (void *) c_fd); pthread_detach(tid);//serve per liberare risorse close(s_fd); return 0; }//end server 38

Sol. Eser. n 3 client.c #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define N 256 int main(int argc, char *argv[]) { int c_fd,portno; struct sockaddr_in sin; struct hostent *hp; char buffer[n]; if (argc!= 3) { printf("illegal number of arguments"); exit(1); } if ((hp = gethostbyname(argv[1])) == 0) { perror("tom: gethostbyname"); exit(1); } 39

Sol. Eser. n 3 client.c c_fd = socket(af_inet, SOCK_STREAM, 0); portno = atoi(argv[2]); sin.sin_family = AF_INET; memcpy((char *)&sin.sin_addr,(char *)hp->h_addr,hp->h_length); sin.sin_port = htons(portno); if(connect(c_fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {printf("connect() failed\n"); return 1; } printf("(client) Scrivere un messaggio: "); fgets(buffer,n,stdin); write(c_fd, buffer, strlen(buffer)); printf("client %d ha inviato il messaggio\n", getpid()); close(c_fd); return 0; }//end client 40

- Esercizio: client/server con socket TCP server interattivo per copia file - 41

Esercizio n 4 Socket TCP Si realizzino una coppia di programmi client/server che, utilizzando i socket TCP come mezzo di trasmissione, copiano file da un processo all'altro. Il processo client, scrive il contenuto del file da trasferire sulla socket, il processo server legge dalla socket e scrive sul nuovo file. Esecuzione: $./server <nome_porta> <nome_nuovo_file> $./client <nome_file_da_trasferire> localhost <nome_porta> Utilizzare come <nome_porta> il numero di matricola. 42

- Passi da compiere - Lato Server Lato Client socket socket bind connect listen open file da trasferire accept read file da trasferire open file write su socket read da socket ----- write su file ----- 43

Sol. Eser. n 4 server.c #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> #include <fcntl.h> #define MAXBUF 8192 int main(int argc, char * argv[]) { int server_socket,connect_socket,portno; int client_addr_len; int retcode,fd; struct sockaddr_in server_addr; char line[maxbuf]; if(argc < 3) { printf("usage:\n%s port nomefilelocale\n",argv[0]); return(0); } 44

Sol. Eser. n 4 server.c printf("server: fase di inizializzazione\n"); server_socket = socket(af_inet,sock_stream,0); if(server_socket == -1) { perror("aprendo il socket del server: "); return(-1); } portno = atoi(argv[1]); server_addr.sin_family = AF_INET; Accetta connessioni dirette a qualunque indirizzo server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(portno); retcode = bind(server_socket,(struct sockaddr*)&server_addr, sizeof(server_addr)); if(retcode == -1) { perror("bind error"); return(-1); } 45

Sol. Eser. n 4 server.c listen(server_socket,1); printf("server: attendo connessione\n"); connect_socket = accept(server_socket,null,null); printf("server: accettata nuova connessione\n Apro file locale %s",argv[2]); fd = open(argv[2],o_wronly O_CREAT, S_IRUSR S_IWUSR); if(fd == -1) {perror("aprendo il file locale"); return(-2);} do {//ciclo di lettura da socket retcode = read(connect_socket,line,maxbuf); if(retcode!= -1) write(fd,line,retcode); //scrittura su file } while(retcode > 0); close(fd);//chiusura file printf("\n Fine del messaggio, chiusura della connessione\n"); close(connect_socket);//chiude la connessione printf("chiusura dei lavori... \n"); close(server_socket);//chiusura socket return(0); }//end server 46

Sol. Eser. n 3 client.c #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <fcntl.h> #define MAXBUF 8192 int main(int argc, char * argv[]) { int client_socket,fd,portno; int retcode,letti; struct sockaddr_in server_addr; char message[maxbuf]; char *nomehost,*filename; if(argc < 4) { printf("usage:\n%s nomefile nomehost portno\n",argv[0]); return(0); } 47

filename = argv[1]; Sol. Esercizio N 4 client nomehost = argv[2]; printf("client (%d): fase di inizializzazione\n",getpid()); client_socket = socket(af_inet,sock_stream,0); if(client_socket == -1) {perror("aprendo il socket del cliente"); return(-1);} portno = atoi(argv[3]); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(portno); memcpy(&server_addr.sin_addr,(gethostbyname(nomehost)->h_addr), sizeof(server_addr.sin_addr)); retcode = connect(client_socket, (struct sockaddr *)&server_addr,sizeof(server_addr)); if(retcode == -1) {perror("connettendo il socket"); return(-1);} fd = open(filename,o_rdonly);//apertura file da trasferire if(fd == -1){ perror("aprendo il file"); return(-1);} 48

Sol. Eser. n 4 client.c do {//ciclo di lettura da file letti = read(fd,message,maxbuf); if(letti > 0) { /* solo se la lettura ha avuto buon fine */ //scrittura su socket retcode = write(client_socket,message,letti); if(retcode == -1) { perror("scrivendo il messaggio"); return(-1);} } } while (letti > 0); printf("client: ho inviato dati dal file %s\n",filename); close(fd); //chiusura file close(client_socket); //chiusura return(0); }//end client 49

- Fine Esercitazione - 50