Lab. di Sistemi Operativi
- Esercitazione n° 11-
- Socket Locali -
1
Sommario
Esercizi su:
Comunicazione FIFO
Socket locali
2
- FIFO -
3
FIFO
4
Esercizio n° 1 – FIFO –
(comunicazione FIFO Client/Server)
Scrivere due programma C, server.c e client.c i quali
comunicano attraverso una FIFO. Il programma server, crea la
fifo “serverFIFO”, la apre in sola lettura e si mette in attesa di
ricevere una richiesta da parte del 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 ha inviato
la richiesta e si rimette in attesa sulla
serverFIFO. Il
programma
client, riempie una struttura
dati scrivendovi il proprio pid, dopodichè invia tale struttura al
server tramite una scrittura
nella serverFIFO, quindi termina
(lanciare i programmi su due shell separate sulla stessa
macchina)
Esecuzione:
$ ./server
$ ./client
5
Sol. Eser. n° 1 – FIFO – server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
typedef struct {
pid_t clientPID;
} richiesta;
int main () {
creazione della FIFO
int fifo;
pid_t figlio;
richiesta buffer;
if (mkfifo("serverFIFO", S_IRUSR | S_IWUSR | S_IXUSR) < 0)
if (errno != EEXIST) {
perror ("Impossibile creare la serverFIFO.\n");
exit (-1);
} /*Continua nella slide successiva*/
6
Sol. Eser. n° 1 – FIFO – server.c
if ((fifo = open ("serverFIFO", O_RDONLY)) == -1) {
perror ("Errore nella open.\n");
exit (-1);
}
while (1) {
read (fifo, &buffer, sizeof (richiesta));
if ((figlio = fork()) < 0) {
perror ("Impossibile creare il figlio.\n");
exit (-1);
}
if (figlio == 0) {
printf ("Pid del Client: %d\n", buffer.clientPID);
break;
}
}
return 0;
}
7
Sol. Eser. n° 1 – FIFO – client.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
typedef struct {
Struttura contenente il pid
pid_t clientPID;
} richiesta;
int main () {
int fifo;
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));
close (fifo);
return 0;
}
8
- Socket locali -
9
Funzione socket
10
Leggere da un socket
11
Scrivere da un socket
12
Il server
13
Il client
14
Esercizio n° 2 – Socket locali–
(- client/server con fork -)
Scrivere due programmi C, server.c e client.c. Il
server.c,
crea una socket locale su cui scriverà il
messaggio da
mandare al client ed un nuovo processo
(fork), ogni volta che inizia una connessione con il
programma client. Tale processo, dovrà leggere sulla
socket il messaggio scritto dal client e scrivere sulla
socket il messaggio da mandare
al client. Il client.c
dovrà creare una socket locale su cui
scriverà il
messaggio da mandare al server
(lanciare l’ esecuzione dei due programmi su due shell
distinti della stessa macchina)
Esecuzione
$ ./server (shell1) MESSAGGIO DA CLIENT: Saluti da client
$ ./client (shell2) MESSAGGIO DA SERVER: Saluti dal
server
15
Sol. Eser. n° 2 server.c
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/types.h>
#include <unistd.h>
int connection_handler(int connection_fd)
{
int nbytes;
char buffer[256];
nbytes = read(connection_fd, buffer, 256);
buffer[nbytes] = 0;
printf("MESSAGGIO DA CLIENT: %s\n", buffer);
nbytes = sprintf(buffer, ”Saluti dal server");
write(connection_fd, buffer, nbytes);
close(connection_fd);
return 0;
}
16
Sol. Eser. n° 2 server.c
int main(void)
{
struct sockaddr_un address;
int socket_fd, connection_fd;
size_t address_length;
pid_t child;
socket_fd = socket(PF_LOCAL, SOCK_STREAM, 0);
if(socket_fd < 0)
{
printf("socket() failed\n");
return 1;
}
unlink("./demo_socket"); /*Rimuove la socket se già esiste */
address.sun_family = AF_LOCAL;
address_length = sizeof(address.sun_family) +
sprintf(address.sun_path, "./demo_socket");
/*Continua nella slide successiva*/
17
Sol. Eser. n° 2 server.c
if(bind(socket_fd, (struct sockaddr *) &address, address_length) !
= 0)
{printf("bind() failed\n");
return 1;}
if(listen(socket_fd, 5) != 0)
{printf("listen() failed\n");
return 1;}
while((connection_fd = accept(socket_fd,
(struct sockaddr *) &address,
&address_length)) > -1)
{ child = fork();
if(child == 0)
{ return connection_handler(connection_fd);
}
close(connection_fd);
}
close(socket_fd);
unlink("./demo_socket"); /*Rimuove la socket*/
return 0;
18
}
Sol. Eser. n° 2 client.c
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
int main(void)
{
struct sockaddr_un address;
int socket_fd, nbytes;
size_t address_length;
char buffer[256];
socket_fd = socket(PF_LOCAL, SOCK_STREAM, 0);
if(socket_fd < 0)
{printf("socket() failed\n");
return 1;}
address.sun_family = AF_LOCAL;
address_length = sizeof(address.sun_family) +
sprintf(address.sun_path, "./demo_socket");
/*Continua nella slide successiva*/
19
Sol. Eser. n° 2 client.c
if(connect(socket_fd, (struct sockaddr *) &address, address_length) !
= 0)
{
printf("connect() failed\n");
return 1;
}
nbytes = sprintf(buffer, “Saluti da client");
write(socket_fd, buffer, nbytes);
nbytes = read(socket_fd, buffer, 256);
buffer[nbytes] = 0;
printf("MESSAGGIO DA SERVER: %s\n", buffer);
close(socket_fd);
return 0;
}
20
Esercizio n° 3 – Socket locali–
(- client/server -)
Scrivere due programmi C, socket-server.c e socketclient.c.
Il
programma socket-server.c, crea una socket
locale e rimane in attesa di ricevere una connessione. Quando
riceve una connessione,
legge il messaggio proveniente da
essa, lo stampa e chiude la connessione. Se il messaggio ricevuto
è “quit”, il programma server, rimuove la socket e termina
l’esecuzione. Il server prende il path
della socket da linea di
comando. Il programma client, si connette alla socket locale ed
invia il messaggio. Il nome del path della
socket e del
messaggio da inviare sono specificati a linea
di comando. (Lanciare i due programmi in due shell distinte)
Esecuzione server:
$ ./socket-server /tmp/socket
Esecuzione client:
$ ./socket-client /tmp/socket “Messaggio”
$ ./socket-client /tmp/socket “quit”
21
Sol. Eser. n° 3 socket-server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
int server (int client_socket)
Legge la lunghezza del
{ while (1)
messaggio dalla socket e la
{ int length; mette in length
char* text; 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; }
22
Sol. Eser. n° 3 socket-server.c
int main (int argc, char* const argv[])
{
const char* const socket_name = argv[1]; int socket_fd, serverLen, clientLen;
int client_sent_quit_message;
struct sockaddr_un serverUNIXAddress;/* Server address */
struct sockaddr_un clientUNIXAddress; /* Client address */
struct sockaddr* serverSockAddrPtr; /* Ptr to server address */
struct sockaddr* clientSockAddrPtr; /* Ptr to client address */
serverSockAddrPtr = (struct sockaddr*) &serverUNIXAddress;
serverLen = sizeof (serverUNIXAddress);
clientSockAddrPtr = (struct sockaddr*) &clientUNIXAddress;
clientLen = sizeof (clientUNIXAddress); /*Continua nella slide successica*/ 23
Sol. Eser. n° 3 socket-server.c
socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0); serverUNIXAddress.sun_family = AF_LOCAL; strcpy (serverUNIXAddress.sun_path, socket_name);
bind (socket_fd, serverSockAddrPtr, serverLen); listen (socket_fd, 5); /* Maximum pending connection length */
/*Continua nella slide successica*/ 24
Sol. Eser. n° 3 socket-server.c
do { int client_socket_fd; client_socket_fd = accept (socket_fd, clientSockAddrPtr, &clientLen);
client_sent_quit_message = server (client_socket_fd);
close (client_socket_fd); } while (!client_sent_quit_message); close (socket_fd); unlink (socket_name); /*Rimuove la socket*/ return 0;
}
25
Sol. Eser. n° 3 socket-client.c
#include
#include
#include
#include
#include
<stdio.h>
<string.h>
<sys/socket.h>
<sys/un.h>
<unistd.h>
void write_text (int socket_fd, const char* text)
{
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);
}
26
Sol. Eser. n° 3 socket-client.c
int main (int argc, char* const argv[])
{
const char* const socket_name = argv[1];
const char* const message = argv[2];
int 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);
serverUNIXAddress.sun_family = AF_LOCAL;
strcpy (serverUNIXAddress.sun_path, socket_name);
connect (socket_fd, serverSockAddrPtr, serverLen);
write_text (socket_fd, message);
close (socket_fd);
return 0;
}
27
Esercizio n° 4 – Socket locali–
(- client/server -)
Scrivere due programmi C, chef.c (server) e cook.c (client).
Il
server crea un socket chiamato “ricetta” e tramite essa
fornisce
una ricetta a tutti i client che la richiedono. La ricetta
è formata da una sequenza di stringhe terminate dal carattere
‘\0’ . Il client
si connette al socket chiamato ricetta e legge la
ricetta fornita dal server. Man mano che il client legge la ricetta
la mostra sullo standard output e quindi termina. Il server, crea
un processo
figlio che evade la richiesta del client. (lanciare i
due programmi,
su due shell distinte della stessa macchina)
Esecuzione:
$ ./chef (shell1)
$ ./ cook (shell2)
28
Sol. Eser. n° 4 chef.c (server)
#include
#include
#include
#include
#include
<stdio.h>
<signal.h>
<sys/types.h>
<sys/socket.h>
<sys/un.h> /* For AFUNIX sockets */
int writeRicette (int fd) {
static char* line1 = “prova, prova, prova, prova,";
static char* line2 = “prova, & prova.";
write (fd, line1, strlen (line1) + 1); /* Write first line */
write (fd, line2, strlen (line2) + 1); /* Write second line
*/
}
/*Continua nella slide successiva*/
29
Sol. Eser. n° 4 chef.c (server)
int main (void) {
int serverFd, clientFd, serverLen, clientLen;
struct sockaddr_un serverUNIXAddress;/* Server address */
struct sockaddr_un clientUNIXAddress; /* Client address */
struct sockaddr* serverSockAddrPtr; /* Ptr to server address
*/
struct sockaddr* clientSockAddrPtr; /* Ptr to client address */
serverSockAddrPtr = (struct sockaddr*) &serverUNIXAddress;
serverLen = sizeof (serverUNIXAddress);
clientSockAddrPtr = (struct sockaddr*) &clientUNIXAddress;
clientLen = sizeof (clientUNIXAddress);
/*Continua nella slide successiva*/
30
Sol. Eser. n° 4 chef.c (server)
serverFd = socket (PF_LOCAL, SOCK_STREAM, 0);
serverUNIXAddress.sun_family = AF_LOCAL; /* Set domain type */
strcpy (serverUNIXAddress.sun_path, "ricetta"); /* Set name */
unlink ("ricetta"); /* Remove file if it already exists */
bind (serverFd, serverSockAddrPtr, serverLen); /* Create file */
listen (serverFd, 5); /* Maximum pending connection length */
while (1) {
clientFd = accept (serverFd, clientSockAddrPtr, &clientLen);
if (fork () == 0) { /* Create child to send receipe */
writeRicette (clientFd); /* Send the recipe */
printf("La ricetta è stata scritta nel socket\n");
close (clientFd); /* Close the socket */
exit (0); /* Terminate */
} else
close (clientFd); /* Close the client descriptor */
}
}
31
Sol. Eser. n° 4 cook.c (client)
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h> /* For AF_UNIX sockets */
int readRicetta (int fd) {
char str[200];
while (readLine (fd, str)) /* Read lines until end-ofinput */
printf ("%s\n", str); /* Echo line from socket */
}
int readLine (int fd, char *str) {
int n;
do { /* Read characters until ’\0’ or end-of-input */
n = read (fd, str, 1); /* Read one character */
} while (n > 0 && *str++ != ’\0’);
return (n > 0); /* Return false if end-of-input */
}
32
Sol. Eser. n° 4 cook.c (client)
int main (void) {
int clientFd, serverLen, result;
struct sockaddr_un serverUNIXAddress;
struct sockaddr* serverSockAddrPtr;
serverSockAddrPtr = (struct sockaddr*) &serverUNIXAddress;
serverLen = sizeof (serverUNIXAddress);
clientFd = socket (PF_LOCAL, SOCK_STREAM, 0);
serverUNIXAddress.sun_family = AF_LOCAL;
strcpy (serverUNIXAddress.sun_path, "ricetta");
/*Continua nella slide successiva*/
33
Sol. Eser. n° 4 cook.c (client)
/*In attesa di connettersi alla socket*/
do {
result = connect (clientFd, serverSockAddrPtr,
serverLen);
if (result == -1) sleep (1); /* Wait and then try again */
} while (result == -1);
readRicetta (clientFd); /* Read the recipe */
close (clientFd); /* Close the socket */
exit (0); /* Done */
}
34
Scarica

esercizi socket locali