Le socket possono essere implementate con svariati linguaggi di programmazione, come c, c# e java. Analizziamo per esempio l’ implementazione in C di un server.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
Dopo aver incluso le opportune librerie indicate sopra viene lanciata la funzione socket per creare un socket, proprio come avviene nel client. Una volta creata una socket, va in qualche modo specificato a quale indirizzo o a quale porta dobbiamo collegarci per istaurare una comunicazione. A tale proposito viene utilizzata la sockaddr, una particolare struttura utilizzata per passare un indirizzo TCP/IP all'interfaccia dei socket. Si noti che implementando un socket lato server, non si conosce a priori la destinazione di tale connessione (dipende daq chi effettua la chiamata). Pertanto l’ indirizzo del destinatario specificato nella sockaddr, conterrà un carattere jolly consentendo al socket di ricevere richieste di connessione da client arbitrari. Inizialmente i socket vengono creati senza alcuna associazione agli indirizzi locali o di destinazione. In molti casi i programmi applicativi non si preoccupano dell'indirizzo locale che usano e vogliono consentire al software del protocollo di sceglierne uno per loro conto. Tuttavia, i server che funzionano su una porta ben nota devono essere in grado di indicare la porta al sistema. A tale proposito una volta creato il socket, il server usa la funzione bind per specificare un indirizzo locale (si associa alla socket un processo). Bind ha la forma seguente:
int bind(int socket, struct sockaddr *localaddr, int addrlen)
L'argomento socket è il descrittore intero del socket da collegare all'indirizzo, localaddr è una struttura che contiene l'indirizzo locale a cui il software dovrebbe essere collegato e addrlen è la lunghezza di quest’ultima. Inizialmente un socket è creato in stato non connesso, che significa che non è associato ad alcuna destinazione esterna. La funzione connect collega permanentemente una destinazione a un socket, ponendolo nello stato connesso. Prima di utilizzare la funzione connect, il server deve preparare un socket per le connessioni in ingresso. Per fare questo si utilizza funzione listen. In termini dei protocolli sottostanti, listen mette il socket in una modalità passiva, pronta ad accettare le connessioni. Quando il server esegue listen, informa anche il sistema operativo che il software del protocollo dovrebbe accodare le richieste che arrivano al socket simultaneamente. La forma è la seguente:
int listen(int socket, int qlenght)
L'argomento socket contiene il descrittore del socket che dovrebbe essere preparato per essere usato dal server e qlenght specifica la lunghezza della coda di richieste per quel socket. Dopo la chiamata, il sistema accoderà fino a qlenght richieste di connessione. Se quando arriva una richiesta la coda è piena, il sistema operativo rifiuterà il collegamento scartando la richiesta. Listen è applicato solo ai socket per cui è selezionato il servizio di consegna a flusso affidabile. Dopo che un server orientato alla connessione ha eseguito la chiamata di sistema listen deve essere in grado di accettare le eventuali connessioni. La chimata accept quindi accetta la richiesta di connessione restituendo una socket con proprietà uguali al genitore. Ha la seguente forma:
int accept (int socket, struct sockaddr *addr, int addrlen )
L'argomento socket specifica il socket descriptor su cui aspettare, addr è un puntatore a una struttura di tipo sockaddr e addrlen è un puntatore a un intero il cui compito è quello di riportare la lunghezza della struttura dell'indirizzo del processo che si è connesso. Quando arriva una richiesta, il sistema riempie l'argomento addr con l'indirizzo del client che ha fatto la richiesta, poi crea un socket la cui destinazione è connessa al client richiedente e ritorna il nuovo descrittore di socket al chiamante. Il socket originale ha ancora la destinazione espressa come carattere jolly e può continuare ad accettare nuove richieste Il server può gestire le richieste interattivamente o simultaneamente.
Nell'approccio interattivo il server gestisce la richiesta stessa, chiude il nuovo socket e poi chiama accept per passare alla richiesta di connessione successiva.
Nell'approccio simultaneo, dopo che è stata completata la chiamata ad accept, il server principale ne crea uno secondario per gestire la richiesta. Il processo secondario eredita una copia del socket, quindi può procedere a servire la richiesta. Quando finisce, il modulo secondario chiude il socket e termina. Il processo server principale chiude la sua copia del nuovo socket dopo aver attivato quello secondario, poi chiama accept per passare alla successiva richiesta di connessione.
Per saperne di più consulta i seguenti approfondimenti:
Tutto quanto riportato in questa pagina è a puro scopo informativo personale. Se non ti trovi in accordo con quanto riportato nella pagina, vuoi fare delle precisazioni, vuoi fare delle aggiunte o hai delle proposte e dei consigli da dare, puoi farlo mandando un email. Ogni indicazione è fondamentale per la continua crescita del sito.