WebSocket e PHP

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Scrivi risposta
Avatar utente
iJim
Prode Principiante
Messaggi: 218
Iscrizione: giovedì 4 febbraio 2010, 15:20
Desktop: ubuntu
Distribuzione: Ubuntu

WebSocket e PHP

Messaggio da iJim »

Sto cercando di scrivere una piccola applicazione in cui il client rimane in attesa di un evento da parte del server.
Sulla parte client utilizzo una WebSocket e sulla parte server utilizzo la socket tramite PHP.
Nella risposta effettuo l'handshake per la webSocket ma c'è qualcosa che non va!

Codice lato client

Codice: Seleziona tutto

function startConnection(){
    var message = 'Ciao';
    var port = 2518;

    // creazione websocket
    var websocket = new WebSocket("ws://localhost:"+ port +"/LipariStudios/tesiLaurea/sketchApps/22/server.php");

    websocket.onopen = function(evt) {
        console.log(evt);

        websocket.send(message);
        websocket.close();
    };
    websocket.onclose = function(evt) { console.log(evt); };
    websocket.onmessage = function(evt) { console.log(evt); };
    websocket.onerror = function(evt) { console.log(evt); };
};
Sul lato server

Codice: Seleziona tutto

// conf
//$host = 'localhost';
//$host = 'liparistudios.hostinggratis.it';
$host = '127.0.0.1';
//$host = '192.168.1.171';
$local = 'LipariStudios/tesiLaurea/sketchApps/22/server.php';   //  local
//$local = 'App/socketTest/01/server.php';   // remote
$data = 'risposta dalla socket';
$port = 2518;

$maxBufferSize = 2048;
$key = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)    or die("Failed: socket_create()");
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)   or die("Failed: socket_option()");
//socket_bind($socket, $host.'/'.$local, $port)             or die("Failed: socket_bind()\n");
socket_bind($socket, $host, $port)             or die("Failed: socket_bind()\n");

// attesa
socket_listen($socket,20)                                 or die("Failed: socket_listen()");

socket_accept($socket);

// connessione in entrata
while(true){
    $numBytes = @socket_recv($socket, $buffer, $maxBufferSize, MSG_WAITALL);
    if ($numBytes === false) {
        $sockErrNo = socket_last_error($socket);
        switch ($sockErrNo)
        {
            case 102: // ENETRESET    -- Network dropped connection because of reset
            case 103: // ECONNABORTED -- Software caused connection abort
            case 104: // ECONNRESET   -- Connection reset by peer
            case 108: // ESHUTDOWN    -- Cannot send after transport endpoint shutdown -- probably more of an error on our part, if we're trying to write after the socket is closed.  Probably not a critical error, though.
            case 110: // ETIMEDOUT    -- Connection timed out
            case 111: // ECONNREFUSED -- Connection refused -- We shouldn't see this one, since we're listening... Still not a critical error.
            case 112: // EHOSTDOWN    -- Host is down -- Again, we shouldn't see this, and again, not critical because it's just one connection and we still want to listen to/for others.
            case 113: // EHOSTUNREACH -- No route to host
            case 121: // EREMOTEIO    -- Rempte I/O error -- Their hard drive just blew up.
            case 125: // ECANCELED    -- Operation canceled

                echo "Unusual disconnect on socket " . $socket;
                // disconnect
                break;
            default:
                echo 'Errore sconosciuto ['. $sockErrNo .']: ' . socket_strerror($sockErrNo);
        }

    }
    elseif ($numBytes == 0) {
        // disconnect
        echo "Client disconnected. TCP connection lost: " . $socket;
    }
    else {
            $tmp = str_replace("\r", '', $buffer);
            if (strpos($tmp, "\n\n") === false ) {
                continue; // If the client has not finished sending the header, then wait before sending our upgrade response.
            }

            // handshake ////////////////////////////////

            // • prendi gli headers e lo componi come un array associativo e lo prendi dul buffer
            $headers = array();
            $lines = explode("\n",$buffer);
            foreach ($lines as $line) {
                if (strpos($line,":") !== false) {
                    $header = explode(":",$line,2);
                    $headers[strtolower(trim($header[0]))] = trim($header[1]);
                }
                elseif (stripos($line,"get ") !== false) {
                    preg_match("/GET (.*) HTTP/i", $buffer, $reqResource);
                    $headers['get'] = trim($reqResource[1]);
                }
            }

            // • prendi il protocolo   //  solitamente chat
            $subProtocol = (isset($headers['sec-websocket-protocol'])) ? $headers['sec-websocket-protocol'] : "";

            // • prendi il sub protocollo  //  solitamente super chat
            $extensions = (isset($headers['sec-websocket-extensions'])) ? $headers['sec-websocket-extensions'] : "";

            // • valore chiave 258EAFA5-E914-47DA-95CA-C5AB0DC85B11

            // • fai lo SHA-1 della key insieme alla chiave
            $webSocketKeyHash = sha1($headers['sec-websocket-key'] . $key);

            // • chr corrispondente ascii di un carattere
            // • hexdec da una stringa esadecimale ne ritorna il valore decimale

            $rawToken = "";
            for ($i = 0; $i < 20; $i++) {
              $rawToken .= chr(hexdec(substr($webSocketKeyHash,$i*2, 2)));
            }
            $handshakeToken = base64_encode($rawToken) . "\r\n";

            // • componi la chiave
//            Sec-WebSocket-Accept: $handshakeToken . $subProtocol . $extensions\r\n

            // • componi la risposta
            $handshakeResponse = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: $handshakeToken$subProtocol$extensions\r\n";

            // oppure
//            $handshakeResponse = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: $handshakeToken$subProtocol$extensions\r\nSec-WebSocket-Protocol: chat";

            // • invia la risposta alla socket
            socket_write($socket,$handshakeResponse,strlen($handshakeResponse));

    }
}


socket_close($socket);
Da queste immagini si vede lo strano comportamento!
Immagine

Immagine
Ultima modifica di iJim il giovedì 12 maggio 2016, 20:28, modificato 2 volte in totale.
Avatar utente
Zoff
Moderatore Globale
Moderatore Globale
Messaggi: 33338
Iscrizione: mercoledì 10 ottobre 2007, 22:36

Re: WebSocket e PHP

Messaggio da Zoff »

Negli script la porta indicata è 2518, nell'immagine è 2516
Prima di aprire una discussione leggi le Guide, poi vedi se c'è un HowTo nel Wiki e fai una ricerca nel Forum!
Applica semplicemente il [Risolto]! Prova: http://forum.ubuntu-it.org/viewtopic.php?f=70&t=548821
Vuoi qualcosa di piu' dal forum? Prova i miei script: http://forum.ubuntu-it.org/viewtopic.php?f=70&t=597066
Avatar utente
iJim
Prode Principiante
Messaggi: 218
Iscrizione: giovedì 4 febbraio 2010, 15:20
Desktop: ubuntu
Distribuzione: Ubuntu

Re: WebSocket e PHP

Messaggio da iJim »

L'immagine è stata fatta qualche tentativo prima...
Avatar utente
Zoff
Moderatore Globale
Moderatore Globale
Messaggi: 33338
Iscrizione: mercoledì 10 ottobre 2007, 22:36

Re: WebSocket e PHP

Messaggio da Zoff »

Hai avviato lo script php prima?
Prima di aprire una discussione leggi le Guide, poi vedi se c'è un HowTo nel Wiki e fai una ricerca nel Forum!
Applica semplicemente il [Risolto]! Prova: http://forum.ubuntu-it.org/viewtopic.php?f=70&t=548821
Vuoi qualcosa di piu' dal forum? Prova i miei script: http://forum.ubuntu-it.org/viewtopic.php?f=70&t=597066
Avatar utente
iJim
Prode Principiante
Messaggi: 218
Iscrizione: giovedì 4 febbraio 2010, 15:20
Desktop: ubuntu
Distribuzione: Ubuntu

Re: WebSocket e PHP

Messaggio da iJim »

Tutti e due gli script sono ospitati su un server Apache.
Io ho bisogno di un meccanismo in cui il server possa inviare in un qualsiasi momento un messaggio al client, che ovviamente era in attesa.
A quanto pare una cosa del genere è possibile utilizzando la WebSocket ( che non mi funziona! )
Avatar utente
Zoff
Moderatore Globale
Moderatore Globale
Messaggi: 33338
Iscrizione: mercoledì 10 ottobre 2007, 22:36

Re: WebSocket e PHP

Messaggio da Zoff »

Il server websocket non è gestito da apache, va lanciato a parte a mano
Prima di aprire una discussione leggi le Guide, poi vedi se c'è un HowTo nel Wiki e fai una ricerca nel Forum!
Applica semplicemente il [Risolto]! Prova: http://forum.ubuntu-it.org/viewtopic.php?f=70&t=548821
Vuoi qualcosa di piu' dal forum? Prova i miei script: http://forum.ubuntu-it.org/viewtopic.php?f=70&t=597066
Avatar utente
iJim
Prode Principiante
Messaggi: 218
Iscrizione: giovedì 4 febbraio 2010, 15:20
Desktop: ubuntu
Distribuzione: Ubuntu

Re: WebSocket e PHP

Messaggio da iJim »

Grazie per la risposta!!!
Purtroppo me ne sono accorto ....
sto facendo un paio di test con il Server-Sent Event
Avatar utente
Zoff
Moderatore Globale
Moderatore Globale
Messaggi: 33338
Iscrizione: mercoledì 10 ottobre 2007, 22:36

Re: WebSocket e PHP

Messaggio da Zoff »

Considera comunque che esistono server PHP belli e pronti: http://socketo.me/

Hello world: http://socketo.me/docs/hello-world
Prima di aprire una discussione leggi le Guide, poi vedi se c'è un HowTo nel Wiki e fai una ricerca nel Forum!
Applica semplicemente il [Risolto]! Prova: http://forum.ubuntu-it.org/viewtopic.php?f=70&t=548821
Vuoi qualcosa di piu' dal forum? Prova i miei script: http://forum.ubuntu-it.org/viewtopic.php?f=70&t=597066
Avatar utente
iJim
Prode Principiante
Messaggi: 218
Iscrizione: giovedì 4 febbraio 2010, 15:20
Desktop: ubuntu
Distribuzione: Ubuntu

Re: WebSocket e PHP

Messaggio da iJim »

Grazie dinuovo per la risposta!
Purtroppo non posso usare nessuna libreria esterna.... devo fare tutto da me!
:(
Avatar utente
Zoff
Moderatore Globale
Moderatore Globale
Messaggi: 33338
Iscrizione: mercoledì 10 ottobre 2007, 22:36

Re: WebSocket e PHP

Messaggio da Zoff »

Ok! Ricorda il [Risolto].
Prima di aprire una discussione leggi le Guide, poi vedi se c'è un HowTo nel Wiki e fai una ricerca nel Forum!
Applica semplicemente il [Risolto]! Prova: http://forum.ubuntu-it.org/viewtopic.php?f=70&t=548821
Vuoi qualcosa di piu' dal forum? Prova i miei script: http://forum.ubuntu-it.org/viewtopic.php?f=70&t=597066
Avatar utente
iJim
Prode Principiante
Messaggi: 218
Iscrizione: giovedì 4 febbraio 2010, 15:20
Desktop: ubuntu
Distribuzione: Ubuntu

WebSocket e PHP

Messaggio da iJim »

Purtroppo sono un tipo testardo!
• lancio lo script da terminale dove c'è la socket PHP in ascolto
// se provo con telnet funziona
• lancio la WebSocket in javascript

e NON ARRIVANO GLI HEADER al server !!!
ma se guardo alla console di chrome gli headers sembrano essere inviati, ho controllato sulle variabili del server e gli header in realtà non arrivano, sembra che partano ma non arrivino mai!!!

Codice: Seleziona tutto

        if (false === ($buffer = socket_read($msgsock, 2048, PHP_NORMAL_READ))) {
            echo "errore nella lettura: " . socket_strerror(socket_last_error($msgsock)) . "\n";
        }

            echo print_r($buffer, TRUE);
            echo print_r($headers, TRUE);
            echo print_r($_REQUEST, TRUE);
            echo print_r($_SERVER, TRUE);
            echo print_r($_GET, TRUE);
            echo print_r(headers_list(), TRUE);
Immagine

Immagine
Avatar utente
iJim
Prode Principiante
Messaggi: 218
Iscrizione: giovedì 4 febbraio 2010, 15:20
Desktop: ubuntu
Distribuzione: Ubuntu

[Risolto] WebSocket e PHP

Messaggio da iJim »

Ho trovato cosa non andava!
La socket ad ogni andata a capo smetteva di rimanere in attesa leggendo di fatto una sola riga, quindi non riuscivo a leggere tutti gli header, tramite un ciclo sono riuscito a raccogliere tutti gli header e a fare l'handshake!
Ho risolto anche un alta cosa tramite un trucco, per lanciare lo script php, basta fare una chiamata Ajax ad uno script php che include lo script da lanciare, basta poi terminare la chiamata Ajax.
In questo modo lo script contenente la socket in ascolto rimane attivo!
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 4 ospiti