简体   繁体   English

WebSockets + PHP套接字不起作用

[英]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. 让我们从头开始:我已经安装了Wamp Server(版本:2.4.9,php:5.5.12) ,并且我想使用Web套接字创建简单的聊天。

Great, for this i create two files: 很好,为此,我创建了两个文件:

Connect.js 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 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 首先,我启动Wamp Server
  • Now I open the file server.php in browser. 现在,我在浏览器中打开文件server.php。
  • 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. 现在可以打开connect.js并查看结果。

When I open connect.js the server.php stop to load in another tab, in console log javascript send to me the following errors: 当我打开connect.js时server.php停止在另一个选项卡中加载,在控制台日志中,javascript向我发送以下错误:

WebSocket connection to 'ws://localhost:8080/' failed: One or more reserved bits are on: reserved1 = 1, reserved2 = 0, reserved3 = 1 WebSocket与'ws:// localhost:8080 /'的连接失败:一个或多个保留位处于打开状态: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). (我不想使用node.js,socket.io和其他,我正在尝试手工完成)。

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服务器,因此,如果您遇到相同的问题,则需要创建一个名为server.php的新文件,并将此代码放在他的下面:

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


?>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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