10-Esercitazione Fifo Socket Locali

download 10-Esercitazione Fifo Socket Locali

of 82

Transcript of 10-Esercitazione Fifo Socket Locali

  • - Comunicazione Tra Processi (IPC) -

    Esercitazione diLab. di Sistemi Operativi 1

    a.a. 2012/2013

    - Comunicazione Tra Processi (IPC) -- 1 Parte -

    1Laboratorio di sistemi operativi a.a. 2012/2013

  • SommarioComunicazione tra processi sulla stessa macchina:

    fifo (qualunque insieme di processi)

    Socket locali

    Comunicazione tra processi su macchine diverse in rete

    Socket TCP (prossima lezione)

    Esercizi:Esercizi:

    fifo

    Socket localiSOCK_STREAM

    SOCK_DATAGRAM

    2Laboratorio di sistemi operativi a.a. 2012/2013

  • - Comunicazione tra processi sulla stessa macchina: FIFO -macchina: FIFO -

    3Laboratorio di sistemi operativi a.a. 2012/2013

  • Le fifo sono pipe con nome che si usano per realizzare unacomunicazione tra processi qualunque, cio non appartenenti alla

    stessa gerarchia (padre figlio)

    Per creare una fifo si usa:

    - Creazione di una fifo: mkfifo -

    #include #include int mkfifo(const char *pathname, mode_t mode);

    Dove:pathname: il nome della fifomode: esprime i permessi sulla fifo (identico a open)

    Restituisce:0 in caso di successo-1 altrimenti

    4Laboratorio di sistemi operativi a.a. 2012/2013

    int mkfifo(const char *pathname, mode_t mode);Esempio duso:

    mkfifo("nomeFIFO", S_IRUSR | S_IWUSR | S_IXUSR);

  • Una volta creata, una FIFO deve essere aperta prima di poterlautilizzare: si utilizza la funzione open

    Quindi la FIFO un tipo di file che ha le caratteristiche di unapipe:

    I dati scritti vengono letti in ordine first-in-first-out.Non possibile rileggere i dati gi letti n posizionarsi allinterno con

    - Apertura/chiusura/eliminazione: fifo -

    #include #include

    fd=open("nomefifo",O_RDONLY | O_WRONLY);

    I dati scritti vengono letti in ordine first-in-first-out.Non possibile rileggere i dati gi letti n posizionarsi allinterno conlseek. (come pipe)La costante PIPE_BUF stabilisce il massimo numero di byte chepossono essere scritti in una FIFO in maniera atomica (come pipe)

    Per chiudere e per eliminare una FIFO si utilizzano lefunzioni: close e unlink (non c bisogno nelle pipe)

    5Laboratorio di sistemi operativi a.a. 2012/2013

    close(fd); unlink("nomefifo");

  • Una volta aperta, si pu accedere alla FIFO come ad unnormale file mediante le funzioni read/write

    Leggere in una FIFO funzione: read

    - Utilizzo: fifo -

    int fd;char msg[10];mkfifo("myfifo", S_IRUSR)fd=open("myfifo", O_RDONLY);read(fd,msg,10);//legge dalla fifo

    Scrivere in una FIFO funzione: write

    6Laboratorio di sistemi operativi a.a. 2012/2013

    read(fd,msg,10);//legge dalla fifo

    int fd;char msg[10];mkfifo("myfifo", S_IWUSR)fd=open("myfifo", O_WRONLY);write(fd,msg,10);//scrive nella fifo

  • - pipe vs fifo -

    PIPE FIFO

    utilizzabile solo da processi gerarchicihanno un nome nel file system e possono essere usate da processi non gerarchici

    create con pipe() create con mkfifo() e aperte con open()

    chiuse con close() si elimina al termine del processo

    chiuse da close() e distrutte da unlink()

    7Laboratorio di sistemi operativi a.a. 2012/2013

  • - Comunicazione client/server half-duplex con FIFO -FIFO -

    8Laboratorio di sistemi operativi a.a. 2012/2013

  • Esercizio n 1 FIFO half-duplexScrivere due programma C, server.c e client.c i quali comunicano

    attraverso una FIFO. Il programma server, crea la fifo serverFIFO, laapre in sola lettura e si mette in attesa di ricevere una richiesta da partedel programma client.Alla ricezione della richiesta, crea un processo figlio,il quale esegue il servizio di stampa a video del pid del processo client che hainviato la richiesta e si rimette in attesa sulla serverFIFO. Il programma

    client, riempie una struttura dati scrivendovi il proprio pid, dopodichinvia tale struttura al server tramite una scrittura nella serverFIFO, quinditermina (lanciare i programmi in due shell separate sulla stessa macchina)

    Esecuzione in due shell diverse sulla stessa macchina

    shell1 $ ./server.outshell2 $ ./client.out

    9Laboratorio di sistemi operativi a.a. 2012/2013

  • - Comunicazione client/server half-duplex con FIFO -

    clientserverread pid

    write pid

    Stampa a video il pid del client

    FIFO half-duplex

    10

    Per interrompere lattivit del server usare la funzione signal:signal(SIGINT, foo); \\CTRL-Cimposta la funzione foo come handler del segnale SIGINT

    Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 1 FIFO server.c#include #include #include #include #include #include #include typedef struct {pid_t clientPID;} richiesta;} richiesta;void disconnetti_fifo();int main () {int fifo;pid_t figlio;richiesta buffer;signal(SIGINT, disconnetti_fifo);//CTRL-Cif (mkfifo("serverFIFO", S_IRUSR | S_IWUSR ) < 0)

    if (errno != EEXIST) {perror ("Impossibile creare la serverFIFO.\n");exit (-1);

    }11

    Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 1 FIFO server.cif ((fifo = open ("serverFIFO", O_RDONLY)) == -1) {

    perror ("Errore nella open.\n");exit (-1);

    }while (1) {//loop infinito

    if( read (fifo, &buffer, sizeof (richiesta)) > 0 ) {

    if ((figlio = fork()) < 0) {perror ("Impossibile creare il figlio.\n");exit (-1);

    }if (figlio == 0) {

    printf("Richiesta di esecuzione di Stampa pid\n");sleep(1);

    printf("Pid del Client: %d\n", buffer.clientPID);}

    }}//end loop} //end server.cvoid disconnetti_fifo(){printf("Server fermato. Rimozione FIFO dal sistema....");unlink("serverFIFO");exit(0);}

    12Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 1 FIFO client.c#include #include #include #include typedef struct {

    pid_t clientPID;} richiesta;int main () {int fifo;richiesta buffer;

    Struttura contenente il pid

    richiesta buffer;if ((fifo = open ("serverFIFO", O_WRONLY)) == -1) {

    perror ("Errore nella open.\n");exit (-1); }

    buffer.clientPID = getpid (); /*Pid del processo*/write (fifo, &buffer, sizeof (buffer));//scrive in fifoclose (fifo); //chiude la fiforeturn 0;}

    13Laboratorio di sistemi operativi a.a. 2012/2013

  • - I Socket -- I Socket -

    14Laboratorio di sistemi operativi a.a. 2012/2013

  • I Socket sono Application Programming Interface (API) usateper interProcess Comunication (IPC)

    Il loro utilizzo giustificato dall avere un interfacciaestremamente potente e flessibile:consentono la comunicazione tra processi eseguiti sulla stessamacchina o tra processi su macchine distribuite in retepossono essere utilizzate insieme a molte famiglie di protocollitra le quali ricordiamo quella dei protocolli di Internet

    - Socket: Generalit -

    tra le quali ricordiamo quella dei protocolli di Internet(TCP/IP).

    Sono referenziabili tramite descrittori cosi come avvieneper i file ottenibili dopo la chiamata alla funzione socket()

    15Laboratorio di sistemi operativi a.a. 2012/2013

  • Forniscono un canale di comunicazione bidirezionale.

    Utilizzate per la comunicazione client/server

    Caratterizzate da descrittori che consentono di utilizzare:read, write e close ecc.

    Due tipi di socket:Socket locali (per processi che risiedono sullo stesso host)Socket TCP (per processi che risiedono su host diversi in rete)

    - Socket: Generalit -

    Socket locali (per processi che risiedono sullo stesso host)Socket TCP (per processi che risiedono su host diversi in rete)

    16

    clientserversocket

    read/write write/read

    Laboratorio di sistemi operativi a.a. 2012/2013

  • La logica su cui si basa la programmazione dei socket semplice,infatti il tipo di comunicazione adottato passa attraverso la definizione didue parametri: dominio e stile

    Il dominio di un una socket equivale alla scelta di una famiglia diprotocolli, ed indica lo spazio in cui risiedono il client e server.

    Ad ogni dominio sono associate una o pi costanti simboliche del tipoPF_nomefamiglia, definite nell header

    - Socket: Domini e stili -

    PF_nomefamiglia, definite nell header

    Tra i domini pi importanti ricordiamo:PF_LOCAL o PF_UNIX per le comunicazioni in locale tramite filesystem (socket locali)PF_INET, la famiglia TCP/IP con Ipv4 (socket TCP)PF_INET6, la famiglia TCP/IP con Ipv6 (socket TCP)

    17Laboratorio di sistemi operativi a.a. 2012/2013

  • A ciascun dominio, possono corrispondere:uno o pi tipi di indirizzi;

    quindi per i socket prevista la nozione di famiglia di indirizziciascuna identificata con una costante simbolica del tipoAF_nomefamiglia definita sempre nell header ;

    I domini finora introdotti dispongono di un unico schema di indirizzi,per cui le attuali implementazioni prevedono lequivalenza tra nomi didominio e nomi di indirizzi.

    - Socket: Indirizzi -

    dominio e nomi di indirizzi.

    18Laboratorio di sistemi operativi a.a. 2012/2013

  • Indirizzamento:consente di individuare le parti coinvolte nella trasmissionestessa. (client e server)

    Gli indirizzi vengono forniti alle socket mediante puntatori adopportune strutture dati i cui nomi incominciano consockaddr_suffisso. (Il suffisso specifica il nome del relativodominio.)

    - Socket: Indirizzamento -

    La struttura degli indirizzi definita nell header come segue:

    struct sockaddr_suffisso {sa_family sa_family, /* Tipo di dominio. AF_xxx */char sa_data[14]; /* Tipo di indirizzo nel dominio */}

    19Laboratorio di sistemi operativi a.a. 2012/2013

  • - Indirizzamento -

    Dominio ITERET

    Domino Locale

    20Laboratorio di sistemi operativi a.a. 2012/2013

  • - Indirizzi per dominio Internet-

    21Laboratorio di sistemi operativi a.a. 2012/2013

  • Lo stile di comunicazione definisce: le caratteristiche dellatrasmissione tra client e serverAd esempio, le trasmissioni possono avvenire a flusso o a pacchetti,

    essere affidabili o no, richiedere o meno una connessione.Lo stile di comunicazione individuato da costanti simbolichedel tipo SOCK_nomestile definite sempre nell header

    Gli stili principali sono:

    SOCK_STREAM, corrispondente ad un canale di trasmissionebidirezionale a flusso, con connessione sequenziale ed affidabile

    - Socket: stili -

    SOCK_STREAM, corrispondente ad un canale di trasmissionebidirezionale a flusso, con connessione sequenziale ed affidabile(paradigma connection oriented).SOCK_DGRAM, che consiste in una trasmissione a pacchetti (datagram)di lunghezza max. prefissata, senza connessione e non affidabile(connectionless).

    Fissato un dominio, la scelta dello stile di comunicazionecorrisponde in pratica ad individuare uno specifico protocollo tra

    quelli consentiti dal dominio stesso.

    22Laboratorio di sistemi operativi a.a. 2012/2013

  • - Comunicazione client/server con Socket -- Comunicazione client/server con Socket -

    23Laboratorio di sistemi operativi a.a. 2012/2013

  • Lato server:crea un socket tramite la funzione socket il cui nome notoanche ai processi client

    Gli assegna un indirizzo con la funzione bind affinch siacondivisibili da altri processi client

    Tramite la funzione listen, attende la connessione al socket daparte dei vari client. La funzione listen crea una coda di lunghezza

    - client/server con socket -

    parte dei vari client. La funzione listen crea una coda di lunghezzaopportuna per consentire la gestione di connessioni simultanee daparte dei client.

    Accetta le connessioni da parte dei client tramite la funzioneaccept, il cui ruolo quello di creare un socket per ogni nuovaconnessione con un client. Tale socket rappresenta il vero canaledi comunicazione tra il client ed il server.

    24Laboratorio di sistemi operativi a.a. 2012/2013

  • Lato server interattivo (un processo client per volta):

    Un client posto in attesa di essere servito sulla coda generata dallafunzione listen aspettando che il server abbia terminato di servire ilclient precedente.

    Lato server concorrente (pi processi client):

    Per ogni client viene generato un processo ad hoc per offrire il serviziorichiesto, in modo che pi client possano essere serviti in modalit

    - client/server con socket -

    richiesto, in modo che pi client possano essere serviti in modalitconcorrente. In tal caso lattesa sulla coda limitata al tempo necessarioalla gestione della richiesta del client da parte del server.

    Una volta creata la connessione con il client, di solito il server, crea unprocesso figlio che si occupa della gestione della connessione, mentre ilprocesso originario continua ad accettare altre connessione da altriclient

    25Laboratorio di sistemi operativi a.a. 2012/2013

  • Lato client:crea un socket anonimo mediate la funzione socket e quindichiede di essere connesso al socket del server

    non presente la funzione bind in quanto il socket creato nondeve essere indirizzabile.

    richiama la funzione connect per stabilire una connessione con ilserver, utilizzando il nome del socket predisposto dal server come

    - client/server con socket -

    server, utilizzando il nome del socket predisposto dal server comeindirizzo.

    Una connessione che ha successo restituisce un descrittore difile al client ed uno al server, che consentono di leggere escrivere sul socket (funzioni read e write)

    26Laboratorio di sistemi operativi a.a. 2012/2013

  • - socket lato server -Crea il socket Fuzione socket

    Gli assegna un indirizzo Funzione bind

    Si mette in ascolto Funzione listen

    Accetta nuove connessioni Funzione accept

    Chiude il socket Funzione close

    Cancella il file se socket locale Funzione unlink

    - socket lato client -

    27

    - socket lato client -Crea il socket Fuzione socket

    Stabilire una connessione Funzione connect

    Chiude il socket Funzione close

    Laboratorio di sistemi operativi a.a. 2012/2013

  • - Funzioni Socket lato server -- Funzioni Socket lato server -

    28Laboratorio di sistemi operativi a.a. 2012/2013

  • Un programma che usa socket deve includere:

    Inoltre deve anche includere: se usa socket del dominio:

    AF_LOCAL o AF_UNIX, socket locali e se usa socketdel dominio:

    - Socket: include -

    del dominio:AF_INET, socket distribuite

    29Laboratorio di sistemi operativi a.a. 2012/2013

  • Funzione socket: creazione

    30Laboratorio di sistemi operativi a.a. 2012/2013

    (STILE)

  • Funzione socket:

    - Esempio: creare un socket locale-

    #include int socket(int famiglia, int tipo, int protocollo);

    socket locale:famiglia = PF_LOCAL oppure PF_UNIX (dominio della socket)tipo = SOCK_STREAM stile (paradigma connection oriented)protocollo = 0 (protocollo di default)

    int socket( PF_LOCAL, SOCK_STREAM, 0 );

    famiglia: specifica il dominio in cui utilizzare il socket Useremo:AF_UNIX oppure AF_LOCAL per socket localiAF_INET per socket distribuite

    tipo specifica il tipo di comunicazione (SOCK_STREAM)protocol specifica il protocollo da utilizzare per la trasmissionedei dati. Se vale 0, indica il protocollo di default per la copiadominio/tipo utlizzato

    31

    int socket( PF_LOCAL, SOCK_STREAM, 0 );

    Laboratorio di sistemi operativi a.a. 2012/2013

  • - Valori per creazione socket -

    32Laboratorio di sistemi operativi a.a. 2012/2013

  • Funzione bind: Assegnare un indirizzo

    33Laboratorio di sistemi operativi a.a. 2012/2013

  • Funzione bind:

    Assegna lindirizzo al socket sockfd, il tipo di indirizzo puessere locale (AF_UNIX) o di rete (AF_INET) a seconda deldominio del socket ed memorizzato nella struttura puntata da

    myaddrAd esempio, per socket locali (AF_LOCAL), lindirizzo il path+il

    - Assegnare un indirizzo ad una socket -

    #include int bind(int sockfd, const struct sockaddr *myaddr,socklen_t addrlen);

    Ad esempio, per socket locali (AF_LOCAL), lindirizzo il path+ilnome del file e la funzione bind fallisce se il file esiste gi (quindiconviene fare prima unlink)

    Mentre per AF_INET lindirizzo rappresentato dal numero diporta e dallindirizzo IP.

    Il terzo argomento addrlen rappresenta la dimensionedellindirizzo (sizeof)Restituisce

    0 se ok-1 altrimenti

    34Laboratorio di sistemi operativi a.a. 2012/2013

  • Funzione bind:Consideriamo la struttura sockaddr_ definita nellinclude

    - Assegnare un indirizzo ad una socket locale -

    #include #define UNIX_PATH_MAX 108struct sockaddr_un {sa_family_t sun_family; //AF_LOCALchar sun_path[UNIX_PATH_MAX]; //pathname del socket};

    Costruzione dell indirizzo per socket locale:

    35

    struct sockaddr_un mio_indirizzo;//Valorizzare i campi della strutturamio_indirizzo.sun_family = AF_LOCAL;strcpy(mio_indirizzo.sun_path, "/tmp/mio_socket");

    bind(fd,(struct sockaddr *)&mio_indirizzo, sizeof(mio_indirizzo));

    Laboratorio di sistemi operativi a.a. 2012/2013

  • Funzione listen: mettersi in ascolto

    36Laboratorio di sistemi operativi a.a. 2012/2013

  • Funzione accept: accettare nuove connessioni

    37Laboratorio di sistemi operativi a.a. 2012/2013

  • Funzione accept:

    Crea un nuovo socket con gli stessi attributi di quello originario,dedicato a questa nuova connessione

    - Accettare una nuova connessione -

    #include

    int accept(int sockfd, struct sockaddr *indirizzo_client,socklen_t *dimensione_indirizzo);

    dedicato a questa nuova connessioneLo connette al socket del client e restituisce un descrittore di file

    corrispondente che permette di comunicare con il clientil vecchio socket resta in ascolto per accettare altre connessioniil secondo e terzo argomento servono ad identificare il client.

    Possono anche essere poste a NULL nel caso che il chiamante(client) non necessiti di indirizzo (ad esempio socket locali)

    RestituisceUn nuovo descrittore se ok-1 altrimenti

    38Laboratorio di sistemi operativi a.a. 2012/2013

  • - Struttura di un server con socket locale -

    int fd1, fd2;struct sockaddr_un mio_indirizzo;

    mio_indirizzo.sun_family = AF_LOCAL;strcpy(mio_indirizzo.sun_path, "/tmp/mio_socket");

    fd1 = socket(PF_LOCAL, SOCK_STREAM, 0);//crea socket locale

    bind(fd1,(struct sockaddr*)mio_indirizzo,

    39Laboratorio di sistemi operativi a.a. 2012/2013

    bind(fd1,(struct sockaddr*)mio_indirizzo,sizeof(mio_indirizzo)); //assegna indirizzo al socket

    listen(fd1, 5);//5 la dim della coda di attesa//attende richieste di connessione da clientfd2 = accept(fd1, NULL, NULL);//per socket locali...close(fd2);close(fd1);unlink("/tmp/mio_socket"); //distrugge il socket

  • - Funzioni socket lato server -Crea il socket fd socket(famiglia, tipo, protocollo)

    Gli assegna un indirizzo bind(fd, indirizzo, dimensione_indirizzo)

    Si mette in ascolto listen(fd, lunghezza_coda)

    Accetta nuove connessioni fd accept(fd, indirizzo_client, dimensione_ind)

    Chiude il socket close(fd)

    Cancella il file se socket locale unlink(nomeFileSocket)

    40Laboratorio di sistemi operativi a.a. 2012/2013

  • - Funzioni Socket lato client -- Funzioni Socket lato client -

    41Laboratorio di sistemi operativi a.a. 2012/2013

  • - Funzioni socket lato client -

    Crea il socket Funzione socket (uguale a quella server)

    Si connette ad un server Funzione connect

    Chiude il socket Funzione close

    42Laboratorio di sistemi operativi a.a. 2012/2013

  • Funzione connect:

    Connette il socket sockfd creato da un client ad un socket il cuiindirizzo presente nella struttura puntata da serv_addr

    #include int connect(int sockfd, const struct sockaddr *serv_addr,

    socklen_t addrlen);

    Funzione connect: connettersi ad un server

    indirizzo presente nella struttura puntata da serv_addril client deve conoscere lindirizzo del serveril terzo argomento la dimensione della struttura dati contenente

    lindirizzoRestituisce

    0 ok-1 altrimenti

    43Laboratorio di sistemi operativi a.a. 2012/2013

  • Funzione close: chiudere il socket

    44Laboratorio di sistemi operativi a.a. 2012/2013

  • - Struttura di un client con socket locale -

    int fd;struct sockaddr_un indirizzo;

    indirizzo.sun_family = AF_LOCAL;strcpy(indirizzo.sun_path, "/tmp/mio_socket");

    fd = socket(PF_LOCAL, SOCK_STREAM, 0);//crea socket localeconnect(fd,(struct sockaddr*)indirizzo, sizeof(indirizzo));

    45

    connect(fd,(struct sockaddr*)indirizzo, sizeof(indirizzo));

    ...close(fd);

    Laboratorio di sistemi operativi a.a. 2012/2013

  • Leggere da un socket

    46Laboratorio di sistemi operativi a.a. 2012/2013

  • Scrivere in un socket

    47Laboratorio di sistemi operativi a.a. 2012/2013

  • - client/server con socket connection oriented -

    48Laboratorio di sistemi operativi a.a. 2012/2013

  • - Esercizi: client/server con Socket locale -(STREAM SOCKET)(STREAM SOCKET)

    49Laboratorio di sistemi operativi a.a. 2012/2013

  • - client/server: con server concorrente multi processo per la gestione di pi client-processo per la gestione di pi client-

    50Laboratorio di sistemi operativi a.a. 2012/2013

  • Esercizio n 4 Socket localiScrivere due programmi C, server.c e client.c. che comunicano

    tramite socket. Il server.c crea una socket locale, ed ogni volta cheinstaura una connessione con un client, mediate fork crea un nuovoprocesso (server concorrente). Tale processo, dovr leggere sulsocket il messaggio scritto dal client e scrivere il messaggio che ilserver manda al client. Il client.c dovr connettersi al socket localesu cui scriver il messaggio da mandare al server.

    (lanciare l esecuzione dei due programmi su due shell distintidella stessa macchina)della stessa macchina)

    Esecuzione$ (shell1) ./server.out MESSAGGIO DA CLIENT: $ (shell2) ./client.out

    Suggerimento:Si utilizzi fgets per ricevere il messaggio da riga di comando

    51Laboratorio di sistemi operativi a.a. 2012/2013

  • - Comunicazione client/server con socket locale -

    clientserver

    fork()

    socket

    legge il messaggio del scrive il messaggio del

    Schema Server concorrente multi-processo per gestire pi

    client

    52Laboratorio di sistemi operativi 1 a.a. 2011/2012

    fork()

    processofiglio gestisci

    legge il messaggio del client dalla socket

    scrive il messaggio del server sulla socket

    Il processo figlio gestisce la connessione con il client Funzione chiamata dal processo

    figlio per gestire la comunicazione con i client

  • - Parametri per creare un socket locale connection oriented -

    #include int socket(int famiglia, int tipo, int protocollo);

    famiglia = PF_LOCAL oppure PF_UNIXtipo = SOCK_STREAM ( paradigma connection oriented )protocollo = 0 ( protocollo di default )int socket( PF_LOCAL, SOCK_STREAM, 0 );

    Indirizzamento:

    53

    #include struct sockaddr_un serverAddress;

    serverAddress.sun_family = AF_LOCAL;strcpy(serverAddress.sun_path, "/tmp/mio_socket");

    bind(fd,(struct sockaddr *)serverAddress,sizeof(serverAddress));

    Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 4 server.c#include #include #include #include #include int gestisci(int connection_fd){

    int nbytes;char buffer[256];//legge da socket il mess. del client

    Funzione chiamata dal processofiglio per comunicare con il clienttramite socket

    sockfd//legge da socket il mess. del clientnbytes = read(connection_fd, buffer, 256);buffer[nbytes] = 0;printf("MESSAGGIO DA CLIENT: %s\n", buffer);nbytes = sprintf(buffer, "Saluti dal server");//Scrive su socket il mess. del serverwrite(connection_fd, buffer, nbytes);close(connection_fd);return 0;

    }

    54Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 4 server.cint main(void) //server{//struttura degli indirizzi di tipo localestruct sockaddr_un serverAddress; //Puntatore alla struttura degli indirizzi struct sockaddr* serverSockAddrPtr;int socket_fd, conn_fd, serverAddressLen; pid_t child;

    socket_fd = socket(PF_LOCAL, SOCK_STREAM, 0);//crea socketif(socket_fd < 0)

    Orientato alla connessione

    if(socket_fd < 0){printf("socket() failed\n");return 1;}

    unlink("demo_socket"); /*Rimuove la socket se gi esiste *///valorizzo i campi della struttura sockaddr_unserverAddress.sun_family = AF_LOCAL; //setta il tipo di dominio

    sprintf(serverAddress.sun_path, "demo_socket");

    //Parametri da passare all funzione bind serverSockAddrPtr = (struct sockaddr*) &serverAddress; serverAddressLen = sizeof (serverAddress);

    55Laboratorio di sistemi operativi 1 a.a. 2011/2012

  • Sol. Eser. n 4 server.cif(bind(socket_fd, serverSockAddrPtr, serverAddressLen) != 0){printf("bind() failed\n");return 1;}

    if(listen(socket_fd, 5) != 0)//si mette in ascolto sulla coda{printf("listen() failed\n");return 1;}

    //crea la connessione con i clientwhile((conn_fd = accept(socket_fd,NULL,NULL)) > -1)

    {{printf("server: new connection from %d \n",conn_fd);child = fork();//server concorrente crea il figlioif(child == 0){return (gestisci(conn_fd)); //comunica con client}close(conn_fd);

    }//end whileclose(socket_fd);unlink("demo_socket"); /*Rimuove la socket*/return 0;

    }//end server56Laboratorio di sistemi operativi 1 a.a. 2011/2012

  • Sol. Eser. n 4 client.c#include #include #include #include int main(void) //client{struct sockaddr_un serverAddress;//Puntatore alla struttura degli indirizzi struct sockaddr* serverSockAddrPtr;int socket_fd, nbytes, serverAddressLen;char buffer[256];

    Orientato alla connessione

    char buffer[256];socket_fd = socket(PF_LOCAL, SOCK_STREAM, 0);//crea socketif(socket_fd < 0){printf("socket() failed\n");return 1;}

    //valorizza i campi della struttura indirizziserverAddress.sun_family = AF_LOCAL;sprintf(serverAddress.sun_path, "demo_socket");

    //Parametri da passare all funzione connect serverSockAddrPtr = (struct sockaddr*) &serverAddress; serverAddressLen = sizeof (serverAddress);

    57Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 4 client.c//si propone di connettersi al socket del serverif(connect(socket_fd, serverSockAddrPtr, serverAddressLen) != 0){printf("connect() failed\n");return 1;}printf("(CLIENT) Scrivere un messaggio: "); fgets(buffer,255,stdin); //immesso da tastiera//scrive su socket il mess. da mandare al serverwrite(socket_fd, buffer, strlen(buffer));write(socket_fd, buffer, strlen(buffer));//legge da socket il mess. del servernbytes = read(socket_fd, buffer, 256);buffer[nbytes] = '\0';

    printf("MESSAGGIO DA SERVER: %s\n", buffer);

    close(socket_fd);

    return 0;}//end client

    58Laboratorio di sistemi operativi a.a. 2012/2013

  • - client/server: con server concorrente multi thread per la gestione di pi client -thread per la gestione di pi client -

    59Laboratorio di sistemi operativi a.a. 2012/2013

  • - Struttura di un server concorrente multiThread-

    socket(...);bind(...);listen(...);

    while (1) {//loop principale

    connect_sd = accept(listen_sd, NULL,NULL)printf("server: new connection from %d \n",connect_sd);pthread_create(&tid,NULL,gestisci,(void *)connect_sd);

    60

    }

    void *gestisci(void *arg) {/* *** fa quello che deve fare *** *//* il thread termina se stesso */pthread_exit(0);}

    Laboratorio di sistemi operativi a.a. 2012/2013

  • Esercizio n 5 Socket localiScrivere due programmi C, serverMultiThread.c e client.c. Ilprogramma serverMultiThread.c, crea una socket locale e rimane inattesa 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 diconnessione. Il programma client, si connette alla socket locale ed invia ilmessaggio passato a riga di comando (usare fgets) al server. Il servertramite il thread legge il messaggio e lo stampa a video

    (Lanciare i due programmi in due shell distinte, e compilare il servercon -lpthread)con -lpthread)

    Esecuzione server:

    shell1 $ ./serverMultiThread.out

    Esecuzione client:shell2 $ ./client.out Messaggio

    61Laboratorio di sistemi operativi a.a. 2012/2013

  • - Comunicazione client/server con socket locale -

    clientserver

    pthread_create()

    socket

    legge il messaggio del

    Schema Server concorrente multi-thread per gestire pi

    client

    62

    pthread_create()

    processothread gestisci

    legge il messaggio del client dalla socket

    stampa il messaggio del client a video

    Il processo thread gestisce la connessione con il client

    Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 5 serverMultiThread.c#include #include #include #include #include

    #define SOCKNAME "mysocket#define N 256

    void *gestisci(void *arg) {

    Funzione chiamata dal thread percomunicare con il client tramitesocket

    void *gestisci(void *arg) { printf("gestisci(): creato il thread\n"); char buf[N];//Legge da socket il messaggio scritto dal client while (read((int *) arg, buf, N) != 0) {

    printf("Server %d : %s\n", getpid(), buf); } close((int *) arg); pthread_exit (0);}

    63Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 5 serverMultiThread.cint main(void) {unlink(SOCKNAME); int s_fd, c_fd; pthread_t tid; struct sockaddr_un sa; sprintf(sa.sun_path, SOCKNAME); sa.sun_family = AF_LOCAL;

    s_fd = socket(AF_LOCAL, SOCK_STREAM, 0); bind(s_fd, (struct sockaddr *) &sa, sizeof(sa)); bind(s_fd, (struct sockaddr *) &sa, sizeof(sa)); listen(s_fd, 5); while (1) { //loop infinito

    c_fd = accept(s_fd, NULL, NULL); printf("server: new connection from %d \n",c_fd); pthread_create(&tid, NULL, gestisci, (void *) c_fd)pthread_detach(tid);

    } return 0;}//end server 64

    Passaggio dell id socket alla funzione gestisci

    Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 5 client.c#include #include #include #include #include #include #include

    #define SOCKNAME "mysocket#define N 256#define N 256

    int main(void) {int c_fd; struct sockaddr_un sa; char buffer[N]; sprintf(sa.sun_path, SOCKNAME); sa.sun_family = AF_UNIX;

    c_fd = socket(AF_UNIX, SOCK_STREAM, 0);

    65Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 5 client.cif(connect(c_fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {

    printf("connect() failed\n"); return 1;

    }

    printf("(CLIENT) Scrivere un messaggio: ");

    fgets(buffer,N,stdin); //Inserimento del messaggio

    write(c_fd, buffer, strlen(buffer)); //scrittura su socket

    printf("Client %d ha inviato il messaggio\n", getpid());

    close(c_fd);

    return 0;

    }//end client

    66Laboratorio di sistemi operativi a.a. 2012/2013

  • - client/server: con server interattivo -- client/server: con server interattivo -

    67Laboratorio di sistemi operativi a.a. 2012/2013

  • Esercizio n 6 Socket localiScrivere due programmi C, socket-server.c e socket-client.c. Ilprogramma socket-server.c, crea una socket locale e rimane in attesa

    di ricevere una connessione. Quando riceve una connessione, legge ilmessaggio proveniente da essa, lo stampa e chiude la connessione. Seil messaggio ricevuto quit, il programma server, rimuove la socket etermina lesecuzione. Il server prende il path della socket da linea dicomando. Il programma client, si connette alla socket locale ed invia ilmessaggio. Il nome del path della socket e del messaggio da inviare sonospecificati a linea

    di comando. (Lanciare i due programmi in due shell distinte)di comando. (Lanciare i due programmi in due shell distinte)Esecuzione server:

    $ ./socket-server demo_socket

    Esecuzione client:shell1 $ ./socket-client demo_socket Messaggioshell2 $ ./socket-client demo_socket quit

    68Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 6 socket-server.c#include #include #include #include #include #include int server (int client_socket) { while (1)

    { int length;char* text;if (read (client_socket, &length, sizeof (length)) == 0)

    Legge la lunghezza del messaggio dalla socket e la mette in length

    chiamata dal server per leggere ilmess. del client nel socket

    if (read (client_socket, &length, sizeof (length)) == 0)return 0;

    text = (char*) malloc (length); /*Alloca memoria per il buffer*/read (client_socket, text, length);/*legge il messaggio e lo mette in text*/printf ("%s\n", text);

    free (text); /*Pulisce il buffer */if (!strcmp (text, "quit")) /*Se text quit termina*/

    return 1;}

    }

    69Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 6 socket-server.cint main (int argc, char* const argv[]) {

    const char* const socket_name = argv[1]; //nome socketstruct sockaddr_un serverUNIXAddress; /*Server address*/struct sockaddr* serverSockAddrPtr; /*Ptr to server address*/int socket_fd, serverLen, clientLen;int client_sent_quit_message;

    socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0);//creazione socket

    //Valorizzo la struttura degli indirizzi//Valorizzo la struttura degli indirizziserverUNIXAddress.sun_family = AF_LOCAL;strcpy (serverUNIXAddress.sun_path, socket_name);

    //Parametri da passare all funzione bindserverSockAddrPtr = (struct sockaddr*) &serverUNIXAddress;serverLen = sizeof (serverUNIXAddress);

    unlink (socket_name);bind (socket_fd, serverSockAddrPtr, serverLen); listen (socket_fd, 5); /* coda di attesa */

    70Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 6 socket-server.cdo {

    int client_socket_fd;

    client_socket_fd = accept (socket_fd, NULL, NULL);

    client_sent_quit_message = server(client_socket_fd);close (client_socket_fd);

    } while (!client_sent_quit_message);//cicla se non quit} while (!client_sent_quit_message);//cicla se non quit

    close (socket_fd); unlink (socket_name); /*Rimuove la socket*/

    return 0;

    } //END SERVER

    71Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 6 socket-client.c#include #include #include #include #include

    void write_text (int socket_fd, const char* text) {

    int length = strlen (text) + 1;

    chiamata dal client per scrivere ilmess. nel socket

    int length = strlen (text) + 1;/*Write the number of bytes in the string, including NUL-termination.*/write (socket_fd, &length, sizeof (length)); write (socket_fd, text, length);

    }

    72Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 6 socket-client.cint main (int argc, char* const argv[]) {

    const char* const socket_name = argv[1];//nome socket const char* const message = argv[2]; //messaggioint serverLen, socket_fd;struct sockaddr_un serverUNIXAddress;struct sockaddr* serverSockAddrPtr;serverSockAddrPtr = (struct sockaddr*) &serverUNIXAddress;serverLen = sizeof (serverUNIXAddress);

    socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0); //crea socket

    serverUNIXAddress.sun_family = AF_LOCAL; strcpy (serverUNIXAddress.sun_path, socket_name); connect (socket_fd, serverSockAddrPtr, serverLen); write_text (socket_fd, message);//scrittura mess. su socket close (socket_fd); return 0;

    } //end client

    73Laboratorio di sistemi operativi a.a. 2012/2013

  • - client/server con Socket locale -connectionless (DATAGRAM SOCKET)connectionless (DATAGRAM SOCKET)

    74Laboratorio di sistemi operativi a.a. 2012/2013

  • - client/server con DATAGRAM SOCKET -

    read()

    75Laboratorio di sistemi operativi a.a. 2012/2013

  • Funzione sendto():

    Manda un messaggio su datagram socket (senza connessione)sockfd: il descrittore della socket su cui mandare il messaggiobuf: il puntatore al messaggio da mandare

    #include #include

    int sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *to, socklen_t tolen);

    Funzione: sendto

    buf: il puntatore al messaggio da mandarelen: la dimensione del messaggioflags: consente di specificare altre info sul messaggio da mandare;

    per messaggi normali viene posto a zeroto: puntatore alla struttura contenete lindirizzo del destinatariodel messaggiotolen: dimensione struttura

    Ritornail numero di byte mandati se ok-1 altrimenti

    76Laboratorio di sistemi operativi a.a. 2012/2013

  • - Esercizi: client/server con Socket locale -(DATAGRAM SOCKET)(DATAGRAM SOCKET)

    77Laboratorio di sistemi operativi a.a. 2012/2013

  • Esercizio n 7 Socket locali Scrivere due programmi C, server.c e client.c. che comunicano

    tramite DATAGRAM socket. Il server.c crea una socket locale, e simette in attesa di leggere un messaggio sulla socket. Il client.cscrivere un messaggio su socket.

    Il nome della socket viene passato al client da riga di comando(lanciare l esecuzione dei due programmi su due shell distintidella stessa macchina)

    EsecuzioneEsecuzione$ ./server.out (shell1) MESSAGGIO DA CLIENT: Saluti da client$ ./client.out socket (shell2)

    78Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 7 server.c#include #include #include #include #include #define NAME "socket" //nome della socketmain(){ int sock, length; struct sockaddr_un name; struct sockaddr_un name; char buf[1024]; /* Create socket from which to read. */ sock = socket(PF_LOCAL, SOCK_DGRAM, 0); if (sock < 0) { perror("opening datagram socket"); exit(1); } /* Create name. */ name.sun_family = AF_LOCAL; strcpy(name.sun_path, NAME);

    79Laboratorio di sistemi operativi a.a. 2012/2013

  • Sol. Eser. n 7 server.c/* Bind the UNIX domain address to the created socket */ if (bind(sock, (struct sockaddr *) &name,

    sizeof(struct sockaddr_un))) {

    perror("binding name to datagram socket"); exit(1); }

    printf("socket -->%s\n", NAME);

    /* Read from the socket */ /* Read from the socket */ if (read(sock, buf, 1024) < 0)

    perror("receiving datagram packet");

    printf("-->%s\n", buf);//STAMPA DEL MESSAGGIO LETTO

    close(sock);

    unlink(NAME);

    }//END SERVER

    80Laboratorio di sistemi operativi a.a. 2012/2013

  • #include #include #include #include #include #define DATA "socket locale connectionlessmain(argc, argv) int argc; char *argv[];{ int sock; struct sockaddr_un name; sock = socket(PF_LOCAL, SOCK_DGRAM, 0); //Crea socket dove scrivere if (sock < 0) {

    Soluzione Esercizio N 7 client.c 1/1

    if (sock < 0) { perror("opening datagram socket"); exit(1); } /* Costruzione indirizzo */ name.sun_family = AF_LOCAL; strcpy(name.sun_path, argv[1]); /* manda message. */ if (sendto(sock, &DATA, sizeof(DATA), 0, (struct sockaddr *)&name,

    sizeof(name)) < 0) { perror("sending datagram message");} close(sock);}//END CLIENT

    81Laboratorio di sistemi operativi a.a. 2012/2013

  • - Fine Esercitazione -- Fine Esercitazione -

    82Laboratorio di sistemi operativi a.a. 2012/2013