Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Network IP
Data Link
Non specificati
Physical
Indirizzi del livello rete (IP)
In internet
– Indirizzo IP (sequenza di 32 bit)
– Per facilitare la sua memorizzazione da parte
dell’uomo viene indicato in notazione decimale
(valore decimale di ogni byte separato da “.”)
es. 10.0.1.4 corrisponde all’indirizzo IP
00001010 | 00000000 | 00000001 | 0000100
Indirizzi del livello Trasporto
(TCP/UDP)
In internet
– coppie <indirizzo IP, porta>
– esempio:
» 158.110.1.2:23 (porta 23: telnet)
Definiscono i punti di accesso presso cui i
processi possono attendere le connessioni
Come conoscerli?
Per alcuni processi sono noti a priori
(“well know ports” di TCP/UDP) (/etc/services)
processo processo
client applicazioni server server
(telnet) (telnet) FTP
livello TCP/UDP 23 21
SAP
livelli 1, 2, 3
Well Know Ports
echo 7/tcp telnet 23/tcp
echo 7/udp smtp 25/tcp
discard 9/tcp time 37/tcp
systat 11/tcp time 37/udp
daytime 13/tcp nameserver 42/tcp
daytime 13/udp whois 43/tcp
netstat 15/tcp tftp 69/udp
ftp 21/tcp gopher 70/tcp
fsp 21/udp gopher 70/udp
ssh 22/tcp www 80/tcp
ssh 22/udp www 80/udp
Fasi di una comunicazione TCP
dichiarazione al sistema operativo che si intende
instaurare nel seguito una connessione (specifica
delle caratteristiche)
apertura della connessione
– diversa nel server e nel client:
» il server assume di definire la connessione prima del client, e
rimane in attesa che il client si connetta alla porta specificata
» il client assume che il server sia già attivo e prova a connettersi
specificando indirizzo e porta del server
scambio di dati bidirezionale (trasmissione e
ricezione)
chiusura della connessione
Alcune primitive
•socket
•socket •bind (indirizzo)
•connect (indirizzo) •listen
•accept (connessione)
•send/receive •send/receive
•close •close
Dichiarazione al sistema operativo
int socket(int domain, int type, int protocol);
è la prima istruzione eseguita sia dal client che dal server
definisce un socket: crea le strutture e riserva le risorse necessarie
per la gestione di connessioni
restituisce un intero che va interpretato come un “descrittore di
file”: un identificatore delle strutture appena create
il client utilizzerà il socket direttamente, specificando il descrittore
di file in tutte le funzioni che chiamerà
il server userà il suo socket indirettamente, come se fosse un
modello o un prototipo per creare altri socket che saranno quelli
effettivamente usati
quando la creazione fallisce, viene restituito il valore -1
Parametri della funzione socket
int domain il valore usuale è AF_INET, cioè “InterNET Address
Family” (comunicazioni tra processi in Internet), si
incontra anche AF_UNIX (comunicazioni tra processi
sullo stesso host unix)
struct sockaddr_in {
short sin_family; famiglia Internet
short sin_port; porta TCP
struct in_addr sin_addr; indirizzo
char sin_zero[8];
}
struct in_addr {
unsigned long int s_addr; indirizzo intero a 32 bit
}
Uso di sockaddr_in
Per convenzione, bisogna sempre settare
TUTTA la struttura indirizzo tutta a zero
prima di riempire i vari campi, usando la
funzione memset().
gestione messaggi
prendi l'input da tastiera
numero "quit"
invia al server numero
chiudi il socket
o "quit"?
server.sin_family = AF_INET;
bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
server.sin_port = htons(atoi(argv[2]));
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses */
}
#define h_addr h_addr_list[0] /* for backward compatibility */
•socket
•socket •bind (indirizzo)
•connect (indirizzo) •listen
•accept (connessione)
•send/receive •send/receive
•close •close
Successione di primitive (con fork)
socket
bind il server ha
riservato un
backlog di 3
server listen 3 connessioni
accept per il socket
server
socket
connect un client si è
connesso
utilizzando una
delle tre possibili
client server connessioni
Successione di primitive (con fork)
fork
client server
server
il processo padre deve chiudere server
il socket appena aperto. Se non
il processo figlio deve
lo fa, il sistema operativo non
chiudere il socket che funge
chiuderà mai la connessione,
da modello, liberandosi di
anche se il processo figlio
tutte le strutture dati (backlog,
chiude il suo socket
ecc.) che non gli servono
Schema a blocchi del server
inizializzazione server
numero quit
numero
numero o
esegui la somma
quit.?
quit
chiudi il socket ed esci
Inizializzazione del server
#include <sys/types.h>
[…altri include…]
if ( argc != 2 ) {
printf("uso: %s <numero-della-porta>\n", argv[0]);
exit(EXIT_FAILURE);
}
server client
socket socket
bind
recvfrom sendto
Esempio client UDP
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
main()
{
int sockid, retcode;
struct sockaddr_in server_addr;
char msg[12]; /* conterra’ il messaggio da inviare */
/* creo il socket */
printf(”client: creo il socket\n");
if ( (sockid = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf(”client: socket() fallita: %d\n",errno);
exit(0);
}
Esempio client UDP (segue)
printf(”client: creating addr structure for server\n");
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(SERV_HOST_ADDR);
server_addr.sin_port = htons(SERVER_PORT_ID);
printf(”client: initializing message and sending\n");
sprintf(msg, ”hello world");
retcode = sendto(sockid,msg,12,0,(struct sockaddr *)
&server_addr,sizeof(server_addr));
if (retcode <= -1)
{ printf("client: sendto failed: %d\n",errno); exit(0); }
close(sockid); /* close the socket */
}
Esempio di server UDP
#define MY_PORT_ID 6090
main()
{
int sockid, nread, addrlen;
struct sockaddr_in my_addr, client_addr;
char msg[50];
printf("server: creating socket\n");
if ( (sockid = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{ printf(”server: socket error: %d\n",errno); exit(0); }
printf(”server: binding my local socket\n");
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = htons(INADDR_ANY);
my_addr.sin_port = htons(MY_PORT_ID);
if ( (bind(sockid, (struct sockaddr *) &my_addr,
sizeof(my_addr)) < 0) )
{ printf(”server: bind fail: %d\n",errno); exit(0); }
printf(”server: starting blocking message read\n");
nread = recvfrom(sockid,msg,11,0,
(struct sockaddr *) &client_addr, &addrlen);
printf(”server: return code from read is %d\n",nread);
if (nread >0) printf(”server: message is: %.11s\n",msg);
close(sockid);
}
Domande
Per quale motivo nell’istruzione recvfrom compare un
parametro che specifica un indirizzo di rete?
Perché recvfrom si usa nelle trasmissioni UDP, che sono non
connesse, e dunque non c’e’ altro modo per sapere in numero IP e
la porta del client (e decidere se è il caso di rispondere)