Socket
Socket
• Ai più diffusi protocolli dello strato applicazione sono stati assegnati numeri di
porta specifici. Ad es., un processo server web (che usa il protocollo HTTP) è
identificato dal numero di porta 80.
•Un elenco di ben conosciuti numeri di porta per tutti i protocolli standard di
Internet è contenuto nella RFC 1700. Quando un programmatore crea una nuova
applicazione, ad esso deve essere assegnato un nuovo numero di porta 1
Unix: strumenti di sincronizzazione, memorizzazione,
comunicazione
2
SOCKET
3
Aspetti caratteristici della comunicazione dei processi
attraverso socket:
4
Proprietà delle socket
• Dominio di comunicazione.
Ambiente nel quale avviene la comunicazione (rete internet: dominio PF-INET;
Stesso S.O. Unix: PF_UNIX)
5
Tipo di socket
Socket stream
- Connection oriented (affidabilità)
- Comunicazione simmetrica uno-a- uno
- Creazione del canale prima dell’inizio della
comunicazione (es., funzione connect);
chiusura del canale al termine della comunicazione(es.:
funzione shutdown).
Socket datagram
- Connectionless (non affidabile)
- Possibilità di comunicazione con più di un processo
(comunicazione asimmetrica)
6
Dominio di comunicazione
Canale
virtuale
Messaggio 1 proc
proc
A B
Messaggio 2
Socket
stream
7
Dominio di comunicazione
Proc
B
Proc
A
Proc
C
Socket
datagram
8
Struttura dati associata alla socket
9
Nel caso del dominio PF-INET l’indirizzo di una socket viene espresso
attraverso questa struttura:
struct sockaddr-in {
sa-family-t sin-family; /*dominio*/
in-port-t sin-port; /*porta*/
struct-in-addr sin-addr; /*[Link]*/
char [Link] [8] /*non usato*/
}
dove il tipo del campo sin_addr, che rappresenta l’indirizzo del nodo, e`
dichiarato nel modo seguente:
struct in_addr { uint32_t s_addr};
10
I tipi di dato non primitivi utilizzati nelle precedenti definizioni sono
descritti nella tabella A. 2, in cui vengono anche indicati i file header in
cui sono contenute le rispettive dichiarazioni.
11
Socket
nodo: indirizzo IP nodo: indirizzo IP
Processo A Processo B
socket
socket
porta
Internet
(TCP/IP) porta
13
FORMATO INDIRIZZI
14
Creazione di una socket
15
Associazione socket - indirizzo locale
16
Comunicazione connection-oriented
(socket STREAM o TCP)
3) fase di comunicazione
17
Comunicazione connection oriented
(lato Server)
18
Comunicazione connection oriented
(lato Client)
19
Comunicazione connection oriented
(lato Server)
nuovo_sd = accept (sd , ind, lun);
int nuovo_sd , sd;
struct sockaddr * ind;
int * lun; Indirizzo è parametro in/out
Processo Processo
Client Server
socket
socket server
client (sd)
listen() +
accept()
socket
server
porta (nuovo_sd)
client read() e write()
rete (TCP/IP) porta
server
21
Protocollo di creazione del canale virtuale
processo client
asc
asc=socket(
crea
richiesta ..)
di
csd=socket csd connessi bind(asc.)
cre
a
(…) one
connect(csd. Listen(asc
ssd
canale crea ssd=accept(asc
virtuale .
<comunicazione
attraverso il <comunicazione
canale> attraverso il
canale>
22
Una volta creato il canale virtuale i due processi agli estremi di esso
(client e server) possono scambiarsi messaggi in entrambe le direzioni
(write, read)
int asc,ssd;
char msg[6] = 34Ciao!34;
write (ssd,msg,6)
23
Processo client
int csd;
char msg[6];
<creazione socket ed apertura del canale>;
read (ssd,msg,6);
24
• Al termine di una sessione di comunicazione, la connessione può essere
chiusa mediante la primitiva
25
Processo client
# include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
struct sockaddr_in *D, *server;
char msg[2000];
int sd, l;
int main()
{
sd=socket(AF_INET,SOCK_STREAM,0);
<inizializzazione indirizzo server>
/* richiesta di connessione*/
connect(sd,&server,l);
27
Socket datagram
Poiché la comunicazione è senza connessione, in questo caso ogni
processo, dopo aver creato la socket ed effettuato l’operazione di binding,
può già utilizzarla per la comunicazione con altri processi.
28
La primitiva di ricezione prevede una sintassi analoga:
29
• La recvfrom può bloccare il processo destinatario, se il messaggio
non è ancora disponibile; a differenza della comunicazione mediante
stream, in questo caso i confini dei messaggi vengono mantenuti , e
il processo quindi viene sospeso fino a che l’intero messaggio non gli
è stato recapitato.
30
Comunicazione senza connessione
(socket DATAGRAM)
Server Process
socket()
Client Process
bind()
socket()
1 recvfrom()
sendto() <attesa
richiesta>
<elaborazione>
2
recvfrom() sendto()
<attesa risp>
close()
close()
31
Process Client
include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
struct sockaddr_in *D, *mio;
char msg[2000], ris[BUFFERSIZE];
int sd, l, addrlen;
main()
{
sd=socket(AF_INET,SOCK_DGRAM,0);
<inizializz. mio indirizzo>
l=sizeof(struct sockaddr_in);
bind (sd,&mio,l);
/* invio messaggio al server: */
sendto (sd, msg, 2000, 0, D,l);
/* ricezione risposta:
recvfrom (sd, ris, BUFFERSIZE,0, D, &addrlen);
...
close(sd);
} 32
Processo server
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
struct sockaddr_in *M, *mio;
char msg[BUFFERSIZE], ris[2000];
int sd, l, addrlen;
main() {
sd=socket(AF_INET,SOCK_DGRAM,0);
<inizializz. mio indirizzo>
l=sizeof(struct sockaddr_in);
bind (sd,&mio,l);
addrlen =l;
/* ricezione messaggio:*/
recvfrom (sd, msg, BUFFERSIZE,0, M, &addrlen);
<calcolo risposta ris>
/*invio risposta:/
sendto (sd, ris, 2000, 0, M, addrlen);
...
33
close(sd); }
Considerazioni conclusive sulle socket UDP
• UDP non è reliable, in caso di perdita del messaggio del Client o della
risposta del Server, il Client si blocca in attesa indefinita della risposta
(utilizzo di timeout?)
• Blocco del Client anche nel caso di invio di una richiesta a un Server non
attivo (errori nel collegamento al server notificati solo sulle socket
connesse)
• UDP non ha flow control, se il Server riceve troppi datagrammi per le sue
capacità di elaborazione, questi vengono scartati, senza nessuna notifica ai
Client
34
Quale tipo di Socket utilizzare?
35
Quale tipo di Socket? Quale livello di trasporto, UDP o TCP?
• affidabilità fondamentale
• l’ordine dei messaggi è importante
• si vuole semantica at-most-once
(servizio del server non idempotente, server con stato)
36
Un esempio: esecuzione remota di comandi
•Il client si pone in attesa della risposta, rappresentata dall’output del comando
eseguito dal server; ogni byte ricevuto attraverso il canale viene copiato dal client
sul dispositivo di standard output.
37
Processo client:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main(int argc, char **argv)
{
int sock, retval, i;
char mess[10], ris[1000];
struct sockaddr_in rem_ind; /*indirizzo socket remota*/
/* Preparazione indirizzo del server */
rem_ind.sin_family = PF_INET; /*dominio*/
/* ad esempio: se l’indirizzo internet del nodo server e`
[Link]:*/
rem_ind.sin_addr.s_addr=inet_addr("[Link]");
rem_ind.sin_port = 22375; /* numero di porta del server*/
38
/* Preparazione del messaggio*/
strcpy(mess, argv[1]);
/* Creazione della socket */
sock=socket(PF_INET, SOCK_STREAM, 0);
connect(sock, &rem_ind, sizeof(struct sockaddr_in));
write(sock,mess, 10); /*invio messaggio*/
while (i=read(sock,ris, 1)>0) /*ric. risposta*/
write(1,ris,i); /* stampa su std. output */
shutdown(sock,2); /* chiusura collegamento*/
}
39
Processo server
• Ogni processo server ha tipicamente una struttura ciclica: ad ogni
iterazione viene servita una particolare richiesta di connessione.
• Per ogni richiesta, dopo aver instaurato una nuova connessione dedicata ad
essa (mediante accept), verrà creato un nuovo processo che: ricevera` dal
canale il nome del comando da eseguire e, successivamente, dopo aver
opportunamente ridirezionato la socket di comunicazione sullo standard
output, passerà ad eseguire il comando mediante una system call della
famiglia exec Al termine dell’esecuzione del comando, il processo server
chiudera` la socket e passera` al servizio di nuove richieste. 40
Processo server:*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
main()
{
char comando[20];
int newsock, sock, figlio, status, i;
struct sockaddr_in mio_ind;
/* Creazione socket di ascolto */
sock=socket(PF_INET, SOCK_STREAM, 0);
/* Preparazione indirizzo socket : */
mio_ind.sin_family=PF_INET;
mio_ind.sin_addr.s_addr = INADDR_ANY;
mio_ind.sin_port=22375;
41
/* Binding:*/
if(bind(sock, &mio_ind, sizeof(struct sockaddr_in))<0)
{
perror("bind");
exit(1);
}
/* sock ricevera` le richieste di connessione: */
listen(sock, 5); /*creaz. coda richieste connessione*/
for (;;)/* ciclo di servizio */
{ /* estrazione nuova richiesta dalla coda: */
newsock=accept(sock,(struct sockaddr_in *) 0, 0);
if ((figlio=fork())==0)
{ /* figlio */
close(sock);
read(newsock, comando, 10); /* ricez. comando*/
/*ridirezione dell’output sulla socket: */
close(1);
dup(newsock);
42
/* esecuzione comando: */
if((i=execlp(comando, comando, (char )0))<0)
{ write(1,"errore", 7);
exit(-1);
}
} /* figlio*/
else /*padre*/
{ wait(&status); /* attesa figlio */
shutdown(newsock, 1); /* chiusura socket: */
close(newsock);
}
}
close(sock);
}
43
Controllato dal Controllato dal
gestore Processo Processo gestore
dell’applicazione dell’applicazione
Socket Socket
44
Processo client Processo server
Socket
del client
byte Socket di
byte connessione
tempo
45