简体   繁体   中英

WebSockets + PHP Sockets not working

Let's start from the beginning: I have installed Wamp Server (version: 2.4.9, php: 5.5.12) , and I want to create a simple chat with web sockets.

Great, for this i create two files:

Connect.js

window.onload = function() { 

var form = document.getElementById('mensagem-formulario'); 
var mensagemTexto = document.getElementById('mensagem');
var listaMensagem = document.getElementById('mensagens');
var socketStatus = document.getElementById('status'); 
var btnFechar = document.getElementById('close'); 

var socket = new WebSocket('ws://localhost:8080');

socket.onopen = function(event) { 

socketStatus.innerHTML = 'Connect with ' + event.currentTarget.URL; socketStatus.className = 'open'; 

};

socket.onerror = function(error) { 

console.log('Error: ' + error); 

socketStatus.innerHTML = 'Error: ' + error;

};

form.onsubmit = function(e) { e.preventDefault(); /
var mensagem = mensagemTexto.value; 
socket.send(mensagem); 
listaMensagem.innerHTML += '<li class="envia"><span>Enviado:</span>' + mensagem + '</li>'; 
mensagemTexto.value = ''; return false; 

};

socket.onmessage = function(event) { 
var mensagem = event.data; listaMensagem.innerHTML += '<li class="recebida"><span>Recebida:</span>' + mensagem + '</li>'; 
};

socket.onclose = function(event) { 

socketStatus.innerHTML = 'Disconectado do WebSocket.'; socketStatus.className = 'closed'; 

};

btnFechar.onclick = function(e) { 
e.preventDefault(); 
socket.close(); return false; 
};

};

Server.php

<?php

    $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
    socket_bind($server, "localhost", 8080);
    socket_listen($server);

    $client = socket_accept($server);

    $message = socket_read($client, 5000);

    $matches = array();

    preg_match('#Sec-WebSocket-Key: (.*)\r\n#', $message, $matches);

    $new_key = new_key($matches[1]);

    $new_message = "HTTP/1.1 101 Switching Protocols\r\n";
    $new_message .= "Upgrade: websocket\r\n";
    $new_message .= "Connection: Upgrade\r\n";
    $new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";

    socket_write($client, $new_message, strlen($new_message));

    $new_message = "Test message !";

    socket_write($client, $new_message, strlen($new_message));

    function new_key($key)
    {
        $key .= "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
        $key = sha1($key);
        $new_key = '';

        for ($i = 0; $i < strlen($key); $i+=2)
        {
            $new_key .= chr(intval($key[$i] . $key[$i+1], 16));
        }

        $new_key = base64_encode($new_key);

        return $new_key;
    }

    /* End of file server.php */

    ?>

Great, now lets test this code:

  • First of all I start my Wamp Server
  • Now I open the file server.php in browser.
  • Great, I think the connection is open (because file doesn't stop to load)
  • Now its time to open connect.js and see the results.

When I open connect.js the server.php stop to load in another tab, in console log javascript send to me the following errors:

WebSocket connection to 'ws://localhost:8080/' failed: One or more reserved bits are on: reserved1 = 1, reserved2 = 0, reserved3 = 1

How can I solve this problem? Is a syntax problem or server problem? (I don't want to use node.js, socket.io and others, I'm trying to do it by hand).

Solution

The problem with this code is the php server, So if you're having the same problem, you need to create a new file called server.php and put this code below inside him:

<?php
error_reporting(E_ALL);
set_time_limit(0);
$adr = "localhost";
echo $adr."\n\n";
$port = 8080;

$m_sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($m_sock, SOL_SOCKET, SO_REUSEADDR, 1);
$cls = array($m_sock);

socket_bind($m_sock, $adr, $port);
socket_listen($m_sock, 5);
echo "Starting server...\n\n";

do{
    usleep(500);
    $changed = $cls;
    $val = @socket_select($changed,$write=NULL,$except=NULL,0);
    foreach ($changed as $sock) {
        if($sock === $m_sock){
            echo "wait...\n\n";
            $msgsock = socket_accept($m_sock);
            array_push($cls, $msgsock);
            echo "Connected...\n\n";
            socket_recv($msgsock, $hds, 4096, 0);

            if(preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$hds,$matchs)){
                echo "do handshake...\n\n";

                $key = $matchs[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
                $key =  base64_encode(sha1($key, true)); 
                $headers = "HTTP/1.1 101 Switching Protocols\r\n".
                "Upgrade: websocket\r\n".
                "Connection: Upgrade\r\n".
                "Sec-WebSocket-Accept: $key".
                "\r\n\r\n";
                socket_write($msgsock, $headers);
                echo "handshak done...\n";
            }
        }else{
            $bytes = socket_recv($sock, $data, 2048, null);
            $d = unmask($data);
            foreach ($cls as $socket) {
                if($socket != $m_sock && $val > 0){
                    try{
                       socket_write($socket,(encode($d))); 
                    }catch(Exception $e){
                        unset($cls[$socket]);
                        socket_close($cls[$socket]);
                    }
                }
            }
        }
    } 


}while(1);
socket_close($m_sock);


function unmask($payload) {
    $length = ord($payload[1]) & 127;

    if($length == 126) {
        $masks = substr($payload, 4, 4);
        $data = substr($payload, 8);
    }
    elseif($length == 127) {
        $masks = substr($payload, 10, 4);
        $data = substr($payload, 14);
    }
    else {
        $masks = substr($payload, 2, 4);
        $data = substr($payload, 6);
    }

    $text = '';
    for ($i = 0; $i < strlen($data); ++$i) {
        $text .= $data[$i] ^ $masks[$i%4];
    }
    return $text;
}

function encode($text)
{
    // 0x1 text frame (FIN + opcode)
    $b1 = 0x80 | (0x1 & 0x0f);
    $length = strlen($text);

    if($length <= 125)
        $header = pack('CC', $b1, $length);
    elseif($length > 125 && $length < 65536)
        $header = pack('CCS', $b1, 126, $length);
    elseif($length >= 65536)
        $header = pack('CCN', $b1, 127, $length);

    return $header.$text;
}


?>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM