Windows Socket
Programming
Corso di Sistemi di Elaborazione delle Informazioni
a.a 2007/2008
Autori:
Alberto Colombo
Fulvio Frati
1
Sommario







Richiami di TCP
Classificazione dei socket
Socket client-server UDP
Socket client-server TCP
Esempio server multiporta
gethostbyname & gethostbyaddr
Java Socket
2
Richiami di TCP: porte


I protocolli TCP e UDP usano le porte per mappare i dati in ingresso
con un particolare processo attivo su un computer.
Ogni socket è legato a un numero di porta così che il livello TCP può
identificare l’applicazione a cui i dati devono essere inviati.
App
App
App
App
App
Porta
Porta
Porta
Porta
Porta
UDP / TCP
#porta Dati
3
Socket: definizione

A livello programmatico, un Socket è definito come un “identificativo
univoco che rappresenta un canale di comunicazione attraverso cui
l’informazione è trasmessa” [RFC 147]

La comunicazione basata su socket è indipendente dal linguaggio di
programmazione.

Client e server devono concordare solo su protocollo (TCP o UDP) e
numero di porta
4
Richiami di TCP: well-known ports

Le porte sono rappresentate da valori interi positivi (16 bit).

Rappresentano punto di collegamento fra strato fisico e applicazioni;
rappresentano un canale di comunicazione

Alcune porte sono state riservate per il supporto di servizi wellknown:





ftp
 21/tcp;
telnet  23/tcp;
smtp  25/tcp;
login  513/tcp.
I servizi e i processi a livello utente generalmente usano un numero
di porta >=1024.
5
Socket: Comunicazione
server
client
Il server riceve
una richiesta da
un client
server
client
Crea un nuovo socket
che dialogherà col client
e torna in ascolto di
altre richieste
richiesta
comm
richiesta
client’
p
fork
p
server
new
socket
comm
client
6
Socket: Classificazione (1)

Datagram Socket:
Utilizzano un protocollo senza connessione  UDP
 Non è necessaria una procedura iniziale di connessione e riconoscimento fra
client e server
 Non dà garanzie di ricezione e ordine dei pacchetti


Stream Socket:
Utilizzano un protocollo con connessione  TCP
 La comunicazione avviene solo fra nodi tra cui è stato stabilito un canale di
comunicazione
 Garantisce ordine e ricezione dei pacchetti


Raw socket:

Dà completo accesso allo strato fisico del sistema per poter sfruttare funzionalità
non implementate dalle interfaccie
 Solo per utenti esperti
7
Socket: Classificazione (2)

Sincroni:

il client ed il server si sincronizzano ad ogni messaggio: sia send() (per
inviare) che receive() (per ricevere) sono bloccanti
 send() ritorna dopo che è stata fatta l’issue della receive
 receive() ritorna solo dopo che il messaggio arriva in coda

Asincrona:
send() non è bloccante, significa che l’operazione ritorna subito dopo
che il messaggio è stato copiato su un buffer locale
 receive() puo’ essere sia bloccante che non. Non bloccante significa
che ritorna subito il controllo all’applicazione, poi tramite polling o
interrupt notificherà l’accodamento del messaggio nella coda

8
Differenze ambiente Unix e Windows

Include files, tutte le librerie raccolte in una:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>




#include <winsock.h>
WSAGetLastError() al posto della variabile errno
closeSocket() al posto di close()
Non supporta Raw Socket
Fork implicito
9
UDP/TCP client: Header
10
UDP/TCP Client: Inizializzazione
librerie
WSAStartup(version, WSAData):
• WORD version, versione delle librerie da caricare
• LPWSADATA WSAData, struttura per ricevere i dettagli della Windows
Socket Implementation
• Necessaria solo in ambienti Windows
11
UDP/TCP Client: Creazione del socket
socket(af, type, protocol):
• int af, famiglia di indirizzi da utilizzare (AF_INET, PF_INET, AF_UNIX);
• int type, tipo di socket (SOCK_STREAM, SOCK_DGRAM);
• int protocol, tipo di protocolo utilizzato (IPPROTO_UDP, IPPROTO_TCP).
• Restituisce un valore negativo se non a buon fine
12
UDP Client: sendTo()
sendTo(socket, echoString, bufferLength, flag, to, toLength):
• int socket, descrittore del socket;
• char* echoString, messaggio da spedire;
• int bufferLength, dimensione in bytes;
• int flags, indica la modalità con cui viene effettuata la chiamata (default 0);
• sockaddr* to, indirizzo destinatario;
• int toLength, dimensione indirizzo in byte.
• Non è necessario una procedura di connessione fra client e server
13
UDP Client: recvfrom()
recvfrom(socket, buffer, bufferLength, flags, from, fromLength):
• SOCKET socket, descrittore del socket;
• char* buffer, messaggio spedito;
• int bufferLength, dimensione in bytes;
• int flags, indica la modalità con cui viene effettuata la chiamata (default 0).
• sockaddr* from, indirizzo mittente;
• int fromLength, dimensione indirizzo in byte.
14
UDP Client: Chiusura socket
closesocket(socket): chiude il socket specificato e ritorna 0 se la chiusura è
andata a buon fine, altrimenti un codice d’errore, recuperabile con
WSAGetLastError().
WSACleanup(): rilascia la libreria.
15
UDP Server: Port Binding
bind(socket, address, addressLength):
• SOCKET socket,descrittore del socket;
• sockaddr* address, indirizzo del socket;
• int addressLength, dimensione dell’indirizzo in byte.
• Lega ogni comunicazione su quel protocollo e su quella porta all’applicazione
16
UDP Server: Ricezione messaggi
• Il server rimane in attesa della ricezione di un messaggio sulla recvfrom()
• Nella struct echoclntAddr sono salvate tutte le informazioni relative al
chiamante (in sin_addr l’indirizzo IP)
17
UDP Socket
Server: INADDR_ANY
Client: servIP
Client
Server
18
TCP Client: Creazione del socket
• Crea un socket basato su TCP di tipo STREAM
19
TCP Client: Connessione
• Stabilisce una connessione verso uno specifico server
connect(socket, address, addressLength):
• SOCKET socket, descrittore del socket;
• sockaddr* address, indirizzo del server;
• int addressLength, dimensione dell’indirizzo in byte.
20
TCP Client: Invio dati
• Invia i dati specificati verso un socket già connesso
• Non è necessario indicare ogni volta l’indirizzo del mittente
send(socket, buffer, bufferLength, flags):
• SOCKET socket, descrittore del socket;
• char* buffer, messaggio da inviare;
• int bufferLength, dimensione del messaggio in byte;
• int flag, indica la modalità con cui viene effettuata la chiamata (default 0).21
TCP Client: Ricezione dati
• Riceve dati da un socket connesso e restituisce il numero di byte ricevuti
• Quando restituisce 0 la comunicazione è interrotta
recv(socket, buffer, bufferLength, flag):
• SOCKET socket, descrittore del socket;
• char* buffer, messaggio da inviare;
• int bufferLength, dimensione del messaggio in byte;
• int flag, indica la modalità con cui viene effettuata la chiamata (default 0).
22
TCP Server: Connessione
• Dopo il bind, il server rimane in ascolto (listen) sul socket;
listen(socket, backlog):
• SOCKET socket, descrittore del socket;
• int backlog, dimensione massima della coda delle connessioni in attesa.
23
TCP Server: Accettazione
• Quando un client richiede la connessione, viene un creato un nuovo socket
per gestire la comunicazione
• Il socket iniziale rimane in attesa di nuove richieste
• accept(socket, clientAddress, clientAddressLength):
• SOCKET socket, descrittore del socket;
• sockaddr* clientAddress, indirizzo del client che ha richiesto l’accesso;
• int clientAddressLength, dimensione di clientAddress in byte.
24
TCP Server: Select (1)
• Permette di gestire simultaneamente più socket che gesticono porte diverse
• Primo passo: creazione di un array di socket ognuno su una porta differente;
nell’esempio la lista delle porte è passata a riga di comando
• Per ogni porta è creato un socket server distinto
25
TCP Server: Select (2)
• La select() ad intervalli specificati, controlla quali socket hanno fatto richiesta
in lettura, scrittura o hanno riscontrato errori di comunicazione e restituisce il
numero di socket interessati
• I socket richiedenti sono marcati ed inseriti in specifici array per le
successive operazioni
select(0,readfds, writefds, errorfds, timeout):
• fd_set* readfs, puntatore all’array di socket in lettura;
• fd_set* writefs, puntatore all’array di socket in scrittura;
• fd_set* errorfs, puntatore all’array di socket controllati per errori;
• timeval* timeout, tempo di attesa per la select
26
TCP Server: Select (3)
• Per capire quali socket hanno richiesto l’accesso, si scorre l’array dei
socket e si applica FD_ISSET()
• FD_ISSET restituisce un valore non-zero se il socket è stato marcato
FD_ISSET(socket, *set):
• SOCKET socket, il descrittore del socket da controllare;
• fd_set *set, puntatore all’insieme dei socket marcati.
27
TCP Server: Select (4)
•
Prima di ogni chiamata a select() è necessario inizializzare l’insieme dei
socket marcabili. Occorre invocare:
1. FD_ZERO() svuota l’insieme dei socket marcati
2. FD_SET(), prepara la lista dei socket attivi, aggiungendo all’insieme il
socket che potrà poi essere marcato dalla select()
28
Esempio Socket paralleli: fork (1)


Duplica il processo
Restituisce:

Al processo padre: pid (Process Id) processo figlio
 Al processo figlio: pid = 0
 In caso di errore: -1





I descrittori aperti dal padre saranno condivisi anche dal figlio
Un descrittore chiuso in un processo rimane aperto nell’altro processo
Crea repliche del processo server per gestire comunicazioni parallele
L’esecuzione ricomincia nel processo figlio dall’istruzione sucessiva alla fork
Chiamata di sistema tipica di Linux, non utilizzabile sotto Windows
29
Esempio Socket paralleli: fork (2)
Sono nel processo padre, chiudo socket
connesso e ritorno all’accept
Sono nel processo figlio, chiudo socket
principale in ascolto e gestisco la
comunicazione con il socket connesso
30
gethostbyname() & gethostbyaddr()
struct hostent *gethostbyname(const char *name);
struct hostent *gethostbyaddr(const void *addr, int len, int type);


Restituiscono un puntatore ad un oggetto di tipo hostent che descrive
un indirizzo internet a partire da un nome o da un indirizzo
Parametri:
name: nome dell’host da ricercare, es. “www.dti.crema.unimi.it”
 addr, puntatore alla struttura in_addr che contiene l’indirizzo
 len, lunghezza in byte della variabile addr
 type, famiglia di indirizzi, es. AF_INET

31
Riassumendo
UDP
TCP
32
Java socket

Server:

Creare un oggetto ServerSocket, specificando il numero di porta a cui
legarlo
 Chiamare accept() per restare in attesa di richieste di connessione
 Quando accept() termina la connessione col client è stabilita
 accept() restituisce un socket per comunicare col client

Client:

Creare un oggetto di tipo Socket, specificando indirizzo e porta
 Quando l’oggetto è costruito la connessione col server è stabilita

La comunicazione avviene direttamente attraverso i canali messi a
disposizione dall’oggetto Socket:

getInputStream(), getOutputStream(), ottengono rispettivamente un
canale di input e di output
33
Java socket: Serializzazione

Il meccanismo della serializzazione permette di scrivere e ricevere
direttamente oggetti (istanze di classi) sui flussi in output e input

Gli oggetti scambiati devono implemetare l’interfaccia Serializable

La maggior parte delle classi standard implementa Serializable
34
Java Socket: Server (1)
//SimpleServer.java: un semplice programma server
import java.net.*;
import java.io.*;
public class SimpleServer {
public static void main(String args[])
throws IOException {
// Registra il servizio sulla porta 1234
ServerSocket s = new ServerSocket(1234);
// Aspetta e accetta una connessione
Socket s1=s.accept();
35
Java Socket: Server (2)
// Ottiene un flusso di comunicazione associato al socket
OutputStream s1out = s1.getOutputStream();
DataOutputStream dos = new DataOutputStream(s1out);
// Invia una stringa!
dos.writeUTF(“Hello world");
// Chiude la connessione, ma non il socket server
dos.close();
s1out.close();
s1.close();
}
}
36
Java Socket: Client (1)
// SimpleClient.java: un semplice programma client
import java.net.*;
import java.io.*;
public class SimpleClient {
public static void main(String args[])
throws IOException {
// Apre la connessione a un server, alla porta 1234
Socket s1 = new Socket(“myserver.dti.unimi.it”,1234);
37
Java Socket: Client (2)
// Ottiene un file handle dal socket e legge l’input
InputStream s1In = s1.getInputStream();
DataInputStream dis = new DataInputStream(s1In);
String st = new String (dis.readUTF());
System.out.println(st);
// Alla fine, chiude la connessione e esce
dis.close();
s1In.close();
s1.close();
}
}
38
Esempio socket paralleli: thread
Server
Client
39
Annotazioni finali

Le slide saranno pubblicate su
http://ra.crema.unimi.it

References:
MSDN – Getting started with Winsock
40