Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
vuoi
o PayPal
tutte le volte che vuoi
GCC
Strumento di linea di comando per la compilazione delle applicazioni
Compila il codice di sorgente scritto nei linguaggi come C e altri
linguaggi macchina per poter essere eseguito dal computer
//gcc server.c -o server
Il linguaggio che verrà utilizzato è C
GBD
Strumendo della linea di comando per il debugging delle applicazioni
Esecuzione passo-dopo-passo
Stampa i parametri dei valori
Forza l’impostazione dei parametri dei valori
GUI disponibile con DDD
//gdb ./server
Ordine dei byte
I dati vengono memorizzati con l'ordine dell’host
L’ordine comune è l’ordine della rete (ovvero Big-endian) 150
Ordine dei byte: conversione
Dall’Host alla rete
- prima che i dati escano fuori nel cavo
Dalla rete all’host
- converte i dati appena entrano dal cavo
Ordine dei byte: funzioni
- htons(): host to network short
- htonl(): host to network long
- ntohs(): network to host short
- ntohl(): network to host long
//Attrezzi utili
Qual’è il mio IP
Iconfig
lista delle interfacce di rete della macchina
Il comando ip
- ip address show 151
- ip link show
Netstat
Lista delle attività del socket su una particolare macchina
- l: per vedere i socket sconnessi (stato di LISTEN)
- p: per vedere i processi legati al socket
- t: per vedere solo i socket TCP
- a: per vedere tutti i socket in ascolto e non in ascolto
Netstat cont’d
Isof
Utile per scoprire la descrizione dei file associato ai processi in
esecuzione (e quindi i socket)
È preferibile l’uso dell’opzione -n per evitare la risoluzione dell’indirizzo e
del nome
Netcat (o nc o ncat)
È in grado di inviare/ricevere qualsiasi tipo di dato sopra TCP o UDP
Modo molto facile per connettersi al server ed esercitarsi con le
intenzioni di debugging
Sintassi: nc <host> <port>
Modalità server (listen): nc -l <host> <port> 152
SSH
Log-in in un altra macchina
ssh <username>@<hostname>
Utile per testare il client/server in esecuzione su macchine differenti
Suggerimenti se la propria applicazione non
funziona
Dal lato del client, prova a connetterti al server
nc <serverIP> <serverPORT>
Dal sito del server, controlla se il socket sta ascoltando
netstat -a | grep <serverPORT>
assicurati di compilare l’ultima versione della tua applicazione
//Programmazione del socket
Socket
Astrazione dalla comunicazione della rete
Operazione Descrizione
Open Prepara per le operazioni di input o output
Close Interrompe le operazioni precedenti e restituisce le risorse
Read Ottiene i dati e li posiziona nella memoria dell’applicazione
Write Mette i dati dalla memoria dell’applicazione e invia il
controllo
Control (ioctl) Imposta le opzioni come le dimensioni del buffer e i
comportamenti della rete 153
Flusso delle chiamate delle funzioni
Costanti del socket
Define address family
Define type of service
Define protocol 154
Address family
Address Family Descrizione
AF_UNIX, AF_LOCAL Comunicazioni locali allo stesso host
AF_INET Protocolli Internet IPv4
AF_INET6 Protocolli Internet IPv6
AF_IPX Protocolli IPX-Novell
AF_NETLINK Interfaccia utente Kemel
AF_X25 Protocolli X25
AF_AX25 Protocolli AX25 delle radio amatoriali
AF_ATMPVC Circuiti virtuali privati ATM (PVC)
AF_APPLETALK Protocolli AppleTalk
AF_PACKET Comunicazione di basso livello dei pacchetti
Socket type
Type Descrizione
SOCK_STREAM Le comunicazioni sono basate sulla connessione, sequenziali,
affidabili e a due vie
SOCK_DGRAM Comunicazione a messaggi senza connessione inaffidabile
utilizzando la lunghezza sistemata
SOCK_SEQPACKET Tipologia di comunicazione a messaggi con pacchetti di
lunghezza sistemata ma sequenziali e più affidabile
SOCK_RAW Accesso ai protocolli crudi della rete
SOCK_RDM Comunicazione affidabile senza connessione, che non utilizza
un particolare ordine dei pacchetti
SOCK_PACKET Obsoleto e non andrebbe utilizzato 155
Una chiamata ai socket
mySocket = socket(AF_INET, SOCK_STREAM, 0);
Dove gli endpoint vengono memorizzati
struct sockaddr_in{
short sin_family; //Tipo di indirizzo
u_short sin_port; //Numero della porta del protocollo
//Ordinamento dei byte della rete
u_long sin_addr; //indirizzo net per l'host remoto
//Ordinamento dei byte della rete
char sin_zero[8]; //inutilizzato, imposta a 0
};
Esempio: Server TCP
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
const char MESSAGGIO [] = "PALLE\n";
int main (int argc, char *argv[]) {
int simpleSocket = 0;
int simplePort = 0;
struct sockaddr_in simpleServer;
//assicurarsi di avere il numero della porta
if(2!=argc){
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
exit(1);
}
} 156
Esempio II
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
//Creazione di un socket di streaming
simpleSocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (simpleSocket==-1){
fprintf(stderr, "Impossibile creare un socket\n");
exit(1);
}else{
fprintf(stderr,"Socket creato");
}
bind()
//Ritira il numero della porta per ascoltare
simplePort = atoi(argv[1]);
//Prepara la struttura dell'indirizzo
//utilizza INADDR_ANY per legare tutti gli indirizzi locali
//nota: usare htonl() e htons()
memset( &simpleServer, '\0', sizeof(simpleServer));
simpleServer.sin_family=AF_INET;
simpleServer.sin_addr.s_addr=htonl(INADDR_ANY);
simpleServer.sin_port=htons(simplePort);
bind() -cont’d
//Lega all'indirizzo e alla porta il nostro socket
returnStatus= bind(simpleSocket(struct sockaddr *)&simpleServer, sizeof(simpleServer));
if(returnStatus==0){
fprintf(stderr,"Legamento completo\n");
}else{
fprintf(stderr, "Impossibile legare l'indirizzo\n");
close(simpleSocket);
exit(1);
} 157
Listen
// ascoltiamo sul socket per le connessioni
returnStatus=listen(simpleSocket,5);
if(returnStatur==-1){
fprintf(stderr, "Impossibile ascoltare il socket\n");
close(simpleSocket);
exit(1);
}
//Il 5 rappresenta il numero massimo di connessioni che il server
può accettare
Listen cont’d 158
accept()
while(1){
//imposta le variabili per gestire la connessione dei client
struct sockaddr_in clientName={0};
int simpleClient=0;
int clientNameLength=sizeof(clientName);
//Blocco all'accettazione delle chiamate delle funzioni
simpleChildSocket=accept(simpleSocket,(struct sockaddr
*)&clientName,&clientNameLength);
if(simpleChildSocket==-1){
frpintf(stderr,"Impossibile accettare la connessione\n");
close(simpleSocket);
exit(1);
}
Write() & close()
//Gestisce la nuova richiesta di connessione
//Scrive il nostro messaggio al client
write(simpleChildSocket,MESSAGE,strlen(MESSAGE));
close(simpleChildSocket);
} //Fine del ciclo while
close(simpleSocket);
return 0;
} 159
Esempio di client TCP
simpleSocket=socket(AF_INET,SOCK_STREAM;IPPROTO_TCP);
...
simplePort=atoi(argv[2]);
memset(&simpleServer,'\0',sizeof(simpleServer));
simpleServer.sin_family=AF_INET;
simpleServer.sin_addr.s_addr=inet_addr(argv[1]);
simpleServer.sin_port=htons(simplePort);
...
//connette all'indirizzo e alla porta con il nostro socket
returnStatus=connect(simpleSocket,(struct scokaddr
*)&simpleServer,sizeof(simpleServer));
...
Esempio di client TCP (cont’d)
//ottiene il messaggio dal server
returnStatus=read(simpleSocket,buffer,sizeof(buffer));
if(returnStatus>0){
printf("%d:%s",returnStatus, buffer);
}else{
fprintf(stderr,"Return Status=%d\n", returnStatus);
} 160
//La prima applicazione di rete
Server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
const char MESSAGE[] = "Ciao utente\n";
int main(int argc, char *argv[]) {
int simpleSocket = 0; //Rappresenta il socket del server
int simplePort = 0; //Il numero della porta su cui il server ascolterà i client
int returnStatus = 0; //Utilizzato per monitorare le chiamate di sistema
struct sockaddr_in simpleServer; //Struttura che contiente l'indirizzo ip e la porta
del server
if(2 != argc) { //Verifica l'argomento
fprintf(stderr, "Utilizzo: %s <portaAscolto>\n", argv[0]);
exit(1);
}
simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Crea il socket
//AF_INET : indica che si tratta di un socket IPv4
//SOCK_STREAM: per una comunicazione orientata alla connessione TCP
//IPPOTRO_TCP: specifica l'utilizzo del protocollo TCP
if(simpleSocket == -1){
fprintf(stderr, "Impossibile creare il socket\n");
exit(1);
}
else{
fprintf(stderr, "Socket creato\n");
}
//Recupera il numero della porta d'ascolto
simplePort = atoi(argv[1]);
//Prepara la struttura dell'indirizzo
//utilizza INADDR_ANY per legare tutti gli indirizzi locali
memset(&simpleServer, '\0', sizeof(simpleServer));
simpleServer.sin_family = AF_INET; //Specifica l'uso del protocollo ipv4
simpleServer.sin_addr.s_addr = htonl(INADDR_ANY); //Il server accetterà connessioni da
qualsiasi interfaccia di rete disponibile
simpleServer.sin_port = htons(simplePort); //Il numero della porta viene convertito nel
formato di rete
//Lega all'indirizzo e alla porta con il nostro socket
returnStatus = bind(simpleSocket,(struct sockaddr *)&simpleServer,
sizeof(simpleServer)); 161
if(returnStatus == 0) {
fprintf(stderr, "Legamento completato\n");
}
else{
fprintf(stderr, "Impossibile creare un legamento con l'indirizzo\n");
close(simpleSocket);
exit(1);
}
//Ascolto sul socket per le connessioni
returnStatus = listen(simpleSocket, 5); //Mette il server in ascolot per connessioni in
ingresso con una coda di massimo 5 connessioni
if(returnStatus == -1){
fprintf(stderr, "Impossibile ascoltare il socket\n");
close(simpleSocket);
exit(1);
}
while (1){
struct sockaddr_in clientName = { 0 };
i