<?php
$servidorSocket=socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($servidorSocket,SOL_SOCKET,SO_REUSEADDR,1);
socket_bind($servidorSocket,'localhost',9000);
socket_listen($servidorSocket);
$clientes=[$servidorSocket];
$null=null;
while(true){
$nuevoClienteLector=$clientes;
socket_select($nuevoClienteLector,$null,$null,10);
if(in_array($servidorSocket,$nuevoClienteLector)){
$nuevoCliente=socket_accept($servidorSocket);
echo "Socket aceptado.\n";
$clientes[]=$nuevoCliente;
$encabezado=socket_read($nuevoCliente,1024);
handshake($nuevoCliente,$encabezado);
$nuevoClienteIndex=array_search($servidorSocket,$nuevoClienteLector);
unset($nuevoClienteLector[$nuevoClienteIndex]);
}
foreach($nuevoClienteLector as $cliente){
while(socket_recv($cliente,$datosCliente,1024,0)>=1){
$mensaje=decodificar($datosCliente);
enviar($clientes,$mensaje);
echo $mensaje."\n";
break 2;
}
$datosCliente=@socket_read($cliente,1024,PHP_NORMAL_READ);
if($datosCliente===false){
$clienteIndex=array_search($cliente,$clientes);
unset($clientes[$clienteIndex]);
echo "Cliente desconectado.\n";
}
}
}
function enviar($clientes,$mensaje){
$mensaje=codificar($mensaje);
foreach($clientes as $cliente){
@socket_write($cliente,$mensaje,strlen($mensaje));
}
}
socket_close($servidorSocket);
function codificar($socketData){
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($socketData);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$socketData;
}
function decodificar($socketData) {
$length = ord($socketData[1]) & 127;
if($length == 126) {
$masks = substr($socketData, 4, 4);
$data = substr($socketData, 8);
}
elseif($length == 127) {
$masks = substr($socketData, 10, 4);
$data = substr($socketData, 14);
}
else {
$masks = substr($socketData, 2, 4);
$data = substr($socketData, 6);
}
$socketData = "";
for ($i = 0; $i < strlen($data); ++$i) {
$socketData .= $data[$i] ^ $masks[$i%4];
}
return $socketData;
}
function handshake($client_socket_resource,$received_header) {
$headers = array();
$lines = preg_split("/\r\n/", $received_header);
foreach($lines as $line){
$line = chop($line);
if(preg_match('/\A(\S+): (.*)\z/', $line, $matches)) $headers[$matches[1]] = $matches[2];
}
$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$buffer = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_socket_resource,$buffer,strlen($buffer));
}