WebSocket e PHP
Inviato: venerdì 6 maggio 2016, 20:24
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
Sul lato server
Da queste immagini si vede lo strano comportamento!


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); };
};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);



