Socket stream
Riprendiamo l'esercizio socket01.php, svolto nella parte introduttiva e, intanto, riscriviamolo introducendo una apposita funzione per la gestione dei messaggi d'errore GestErr. Focalizziamo, inoltre, l'attenzione sul fatto che la scrittura dello script è stata molto facilitata dalle apposite estensioni del PHP dedicate ai socket, ossia tutte le funzioni usate che iniziano per socket_ e che ci sono servite per creare, connettere, chiudere i socket, ed altro ancora.
Esecuzione dello script
Dopo aver salvato il codice precedente nella cartella public_html
dandogli il nome socket01b.php
, lo possiamo mandare in esecuzione direttamente dalla riga di comando di un terminale:
$ php ~/public_html/socket01b.php
ottenendo in risposta:
Socket creato correttamente. Connessione attivata. Invio messaggio riuscito. HTTP/1.0 302 Found Cache-Control: private Content-Type: text/html; charset=UTF-8 Location: http://www.google.it/?gfe_rd=cr&ei=0RXyVIXGLsuG8QfMxYCYBg Content-Length: 258 Date: Thu, 26 Feb 2015 17:28:48 GMT Server: GFE/2.0 Alternate-Protocol: 80:quic,p=0.08 <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>302 Moved</TITLE></HEAD><BODY> <H1>302 Moved</H1> The document has moved <A HREF="http://www.google.it/?gfe_rd=cr&ei=0RXyVIXGLsuG8QfMxYCYBg">here</A>. </BODY></HTML>
Come si può facilmente constatare, il risultato ottenuto è esattamente lo stesso dell'esempio precedente.
La funzione interna PHP fsockopen
Ma, a questo punto vogliamo far notare che per risolvere i problemi con i socket non è necessario utilizzare le estensioni PHP che abbiamo usato finora. Lo stesso problema di prima può essere risolto utilizzando la tecnica dei file stream.
In questo caso la funzione fsockopen crea contemporaneamente il socket e la connessione, e non è necessario conoscere l'indirizzo IP ma è sufficiente specificare il nome del dominio. La funzione fwrite invia il messaggio e la funzione fgets riceve i dati. Molto semplice e simile alle operazioni di lettura/scrittura da flussi di file.
Esecuzione dello script
Dopo aver salvato il codice precedente nella cartella public_html
dandogli il nome socket01c.php
, lo possiamo mandare in esecuzione direttamente dalla riga di comando di un terminale:
$ php ~/public_html/socket01c.php
ottenendo in risposta:
HTTP/1.0 302 Found Cache-Control: private Content-Type: text/html; charset=UTF-8 Location: http://www.google.it/?gfe_rd=cr&ei=wCvyVOnuDKms8wfBs4FY Content-Length: 258 Date: Thu, 26 Feb 2015 17:28:48 GMT Server: GFE/2.0 Alternate-Protocol: 80:quic,p=0.08 <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>302 Moved</TITLE></HEAD><BODY> <H1>302 Moved</H1> The document has moved <A HREF="http://www.google.it/?gfe_rd=cr&ei=wCvyVOnuDKms8wfBs4FY">here</A>. </BODY></HTML>
Funzioni interne del PHP per i socket
Il lavoro precedente ha prodotto una connessione di rete senza la necessità di utilizzare necessariamente le estensioni di PHP per i socket. Naturalmente se le estensioni sono state aggiunte è stato fatto per rendere il PHP più completo, ma il linguaggio stesso consente tuttavia di portare a termine le operazioni più tipiche con i socket semplicemente sfruttando alcune sue funzioni interne.
Nell'esempio precedente è stato creato un socket TCP, invece per creare un socket UDP, sempre con l'uso della funzione fsockopen
, bisogna specificare nei suoi primi 2 parametri il cosiddetto socket stream wrapper, come qui di seguito indicato:
$fp = fsockopen("udp://127.0.0.1", 13, $errno, $errstr);
Nel socket stream wrapper per TCP naturalmente ci sarà tcp:// al posto di udp://, mentre la sintassi generale sarà :
$protocol://$host:$port
L'uso delle funzioni interne costituisce, quando possibile, una alternativa facile e veloce per lavorare con i socket, senza caricare il PHP di altro lavoro supplementare. Esiste un'altra funzione, chiamata stream_socket_client
che svolge più o meno lo stesso lavoro di fsockopen
.
$fp = stream_socket_client("tcp://www.google.it:80", $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br />n"; }
La sua struttura è quasi identica a quella di fsockopen
, tranne per il fatto che il numero di porta viene passato assieme al primo parametro, separato dai due punti.
Un'altra versione di server
Le funzioni interne del PHP consentono anche di gestire dei server, come viene fatto con il codice seguente che mette in attesa un semplice server per rispondere alle richieste di un client.
Esecuzione dello script
Dopo aver salvato il codice precedente nella cartella public_html
dandogli il nome stream01.php
, lo possiamo mandare in esecuzione direttamente dalla riga di comando di un terminale:
$ php ~/public_html/stream01.php
ottenendo in risposta:
In attesa delle connessioni...
Apriamo adesso un altro terminale e digitiamo:
$ telnet localhost 4444
otterremo in risposta:
Trying ::1... Trying 127.0.0.1... Connected to localhost. Escape character is '^]'.
che ci avverte dell'avvenuta connessione. Il nostro semplice server è in grado di svolgere soltanto il servizio di eco, un client per volta. Infatti inviando dal nostro terminale client dei messaggi otterremo soltanto la replica del messaggio inviato. Non solo, ma se apriamo un terzo terminale come client telnet, quest'ultimo sarà servito soltanto quando avremo chiuso il precedente.
Attivazione di connessioni multiple
Quindi occorrerà riscrivere meglio il codice per consentire la gestione di connessioni multiple.
Esecuzione dello script
Dopo aver salvato il codice precedente nella cartella public_html
dandogli il nome stream02.php
, lo possiamo mandare in esecuzione direttamente dalla riga di comando di un terminale:
$ php ~/public_html/stream02.php
ottenendo in risposta:
In attesa delle connessioni...
Questa volta aprendo vari terminali telnet ognuno di essi verrà servito subito ed in maniera indipendente dagli altri. L'apertura e la chiusura dei vari terminali verrà segnalata regolarmente sul terminale del server. Una tipica schermata del terminale del server potrebbe essere simile alla seguente:
In attesa delle connessioni... Connessione accettata da 127.0.0.1:34391 TOTALE client connessi: 1 Connessione accettata da 127.0.0.1:34393 TOTALE client connessi: 2 Connessione accettata da 127.0.0.1:34395 TOTALE client connessi: 3 Un client si è disconnesso. TOTALE client connessi: 2 Un client si è disconnesso. TOTALE client connessi: 1
L'output precedente mostra che prima si sono collegati 3 client e poi 2 di essi si sono scollegati.
Punto della situazione
In questa sezione abbiamo imparato come:
1 - Migliorare la struttura di uno script
2 - Utilizzare la funzione fsockopen
3 - Usare alcune funzioni interne del PHP per i socket
4 - Scrivere un semplice server con le funzioni interne
La ricchezza del mio cuore è infinita come il mare, così profondo il mio amore; più te ne dò, più ne ho, perché entrambi sono infiniti.
William Shakespeare