Ottenere l'indirizzo IP dal nome del dominio
Adesso è arrivato il momento di far svolgere al server alcune attività tramite i socket. Ma prima di andare avanti ci sono alcuni argomenti collaterali che devono essere compresi nel caso ce ne fosse la necessità .
Quando ci si collega ad un host remoto è necessario poter disporre de suo indirizzo IP. La funzione gethostbyname
è quella che fa al nostro scopo, essa prende il nome del dominio come parametro e ne restituisce l'indirizzo IP.
$ip_address = gethostbyname("www.google.it"); // = 173.194.75.104
Quindi con il codice precedente, dal nome di qualsiasi dominio, si può trovare il suo indirizzo IP, e con questo si può stabilire una connessione utilizzando un socket.
Programmazione di un server
Occupiamoci quindi delle attività riguardanti i server, i quali svolgono essenzialmente i seguenti lavori:
1 - Aprono un socket
2 - Lo associano ad un indirizzo e ad una porta (Binding)
3 - Ascoltano se arrivano connessioni
4 - Accettano le connessioni
5 - Leggono e rispondono
Bind di un socket
Abbiamo già visto come aprire un socket, occupiamoci adesso di vedere come si effettua il bind.
La funzione socket_bind
è quella che serve per legare un socket ad un particolare indirizzo e ad una porta. Ha bisogno di una struttura sockaddr_in
simile a quella della funzione socket_connect.
if (!($sock = socket_create(AF_INET, SOCK_STREAM, 0))) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("Creazione del socket non riuscita: [$errorcode] $errormsg \n"); } echo "Socket creato correttamente. \n"; // Bind del socket con l'indirizzo e la porta if ( !socket_bind($sock, "127.0.0.1" , 5000) ) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("Bind non riuscito: [$errorcode] $errormsg \n"); } echo "Bind effettuato con successo. \n";
Una volta realizzato il bind si può procedere all'ascolto delle connessioni. Avendo legato il socket a quel particolare indirizzo IP ed a quel numero di porta, ci assicuriamo che tutti i dati in entrata diretti a quel numero di porta vengono ricevuti da questa applicazione.
Questo rende evidente che non si possono avere 2 socket legati alla stessa porta, ma ci sono delle eccezioni a questa regola, di cui ci occuperemo successivamente.
Ascolto di connessioni
Dopo aver vincolato un socket ad una porta, la prossima cosa da fare è di mettersi in ascolto per le connessioni. Per questo occorre mettere il socket in modalità di ascolto. Per raggiungere lo scopo si utilizza la funzione socket_listen
, aggiungendo allo script la riga seguente.
// Impostazione in ascolto socket_listen ($sock , 10)
Il secondo parametro della funzione socket_listen viene chiamata backlog
e controlla il numero di connessioni in ingresso che vengono tenute in "attesa", se il programma è già occupato. Quindi specificando il valore 10 significa che se ci sono già 10 collegamenti in attesa di essere processati allora la richiesta di connessione per l'11ma viene respinta. Questo risulterà più chiaro dopo aver visto la funzione socket_accept
.
Accettare una connessione
La parte principale del lavoro consiste nell'accettare le nuove connessioni, questo si realizza tramite la funzione socket_accept
.
Esecuzione dello script
Dopo aver salvato il codice precedente nella cartella public_html
dandogli il nome socket02.php
, lo possiamo mandare in esecuzione direttamente dalla riga di comando di un terminale:
$ php ~/public_html/socket02.php
ottenendo in risposta:
Socket creato correttamente. Bind del socket OK. Ascolto del socket OK. In attesa dell'arrivo delle connessioni...
Adesso il programma è in attesa di connessioni in ingresso sulla porta 5000. Non chiudere il programma e lasciarlo in esecuzione. Adesso un client sarà in grado di connettersi ad esso su questa porta, e per farlo utilizzeremo telnet come programma di test. Aprire un secondo terminale e digitare:
$ telnet localhost 5000
Immediatamente sul secondo terminale arriverà la risposta:
Trying ::1... Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Connection closed by foreign host.
Mentre sul primo terminale si vedrà il messaggio:
Client 127.0.0.1 : 38168 risulta collegato.
Quanto accaduto dimostra come il client si sia connesso al server. Provare i passaggi precedenti fino ad ottenere un funzionamento perfetto.
Nota
La funzione socket_getpeername
viene utilizzata per ottenere i dettagli relativi al client che è collegato al server tramite un determinato socket.
Nell'esempio precedente dopo aver accettato una connessione in entrata l'abbiamo chiusa immediatamente. Questo non è molto produttivo, ci sono tante cose che si possono fare dopo aver stabilito una connessione. Dopotutto il collegamento è stato effettuato con lo scopo di comunicare, quindi di consentire di rispondere al client.
La funzione socket_write
consente al server di scrivere qualcosa sul socket in modo che il client la possa vedere. Ecco un esempio:
Esecuzione dello script
Dopo aver salvato il codice precedente nella cartella public_html
dandogli il nome socket03.php
, lo possiamo mandare in esecuzione direttamente dalla riga di comando di un terminale:
$ php ~/public_html/socket03.php
ottenendo in risposta:
Socket creato correttamente. Bind del socket OK. Ascolto del socket OK. In attesa dell'arrivo delle connessioni...
Mentre il server gira su un terminale, apriamo un secondo terminale e facciamo girare il client telnet:
$ telnet localhost 5000
Immediatamente sul secondo terminale arriverà la risposta:
Trying ::1... Trying 127.0.0.1... Connected to localhost. Escape character is '^]'.
mentre sul primo terminale arriverà il messaggio di conferma:
Client 127.0.0.1 : 35181 risulta collegato.
Ancora sul secondo terminale digitiamo un messaggio, seguito da [Invio]:
$ ciao a tutti
ottenendo in risposta:
OK ... ciao a tutti Connection closed by foreign host.
Mentre sul primo terminale verrà chiusa la connessione.
Abbiamo visto, quindi, come il client telnet abbia ricevuto una risposta dal server, e come la connessione sia stata chiusa subito dopo, per il solo fatto che il programma server termina dopo aver accettato un messaggio e spedito una risposta. Invece un server come www.google.it rimane sempre in ascolto per accettare delle connessioni in entrata. Ciò significa che un server dovrebbe essere sempre in esecuzione. D'altra parte il significato della parola server è proprio quello di servire.
Punto della situazione
In questa sezione abbiamo imparato come:
1 - Ottenere l'indirizzo IP dal nome del dominio
2 - Effettuare il Bind di un socket
3 - Mettere un socket server in ascolto
4 - Accettare una connessione
5 - Utilizzare telnet come client di prova
Diffidate dell'uomo che inneggia alla liberazione della donna: sta meditando di lasciare il lavoro.
Erica Jong