Javascript 创建PHP websockets服务器

Javascript 创建PHP websockets服务器,javascript,php,apache,websocket,Javascript,Php,Apache,Websocket,我是WebSocket技术的新手。我试图创建一个websockets php服务器,并使用javascript客户端连接到该服务器。我使用的是XAMPP1.8.3 我制作了这个简单的PHP服务器: <?php error_reporting(E_ALL); set_time_limit(0); $address = "127.0.0.1"; $port = 1777; $maxConnections = 10; if(!($sock =

我是WebSocket技术的新手。我试图创建一个websockets php服务器,并使用javascript客户端连接到该服务器。我使用的是XAMPP1.8.3

我制作了这个简单的PHP服务器:

<?php 
    error_reporting(E_ALL);
    set_time_limit(0);

    $address = "127.0.0.1";
    $port = 1777;
    $maxConnections = 10;

    if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0))){
        $errorCode = socket_last_error();
        $errorMsg = socket_strerror($errorCode);
        die("socket_create() failed -> {$errorCode}:{$errorMsg}\n");
    }
    echo "Server created.\n";

    if(!(socket_bind($sock, $address, $port))){
        $errorCode = socket_last_error();
        $errorMsg = socket_strerror($errorCode);
        die("socket_bind() failed -> {$errorCode}:{$errorMsg}\n");
    }
    echo "Server opened on {$address}:{$port}\n";

    if(!(socket_listen($sock, $maxConnections))){
        $errorCode = socket_last_error();
        $errorMsg = socket_strerror($errorCode);
        die("socket_listen() failed -> {$errorCode}:{$errorMsg}\n");
    }
    echo "Waiting for connections...\n";

    $client = socket_accept($sock);
    if(socket_getpeername($client, $address, $port)){
        echo "The client {$address}:{$port} is online.\n";
    }
    $msg = socket_read($client, 1024000);
    if(!(socket_write($client, $msg, strlen($msg)))){
        $errorCode = socket_last_error();
        $errorMsg = socket_strerror($errorCode);
        die("socket_write() failed -> {$errorCode}:{$errorMsg}\n");
    }
    echo "Message sent\n";

    socket_close($client);
    socket_close($sock);


?>
我在shell上得到了这样的信息:

php htdocs/server.php
Server created.
Server opened on 127.0.0.1:1777
Waiting for connections...
然后我在chrome上打开了client.html(我的支持websockets)。 My client.html代码是:

<html>
    <head>
        <meta charset="UTF-8" />
        <title>Websockets web-server connection</title>
    </head>
    <body>
        <p>Websockets connection. Status: <span id="status"></span></p>
        <script type="text/javascript">
            var webSockets = new WebSocket("ws://127.0.0.1:1777/");
            webSockets.onopen = function(){
                document.getElementById("status").innerHTML="connected";
                webSockets.send("ping");
            }
        </script>
    </body>
</html>
我的外壳上有这样的信息:

php htdocs/server.php
Server created.
Server opened on 127.0.0.1:1777
Waiting for connections...
The client 127.0.0.1:64446 is online
Message sent
然而,我并没有在客户端上收到任何消息,我甚至并没有获得连接状态

发生了什么事?我的错误在哪里


谢谢。

WebSocket不是原始TCP套接字。它们需要一个相当复杂的类似HTTP的握手来建立连接,并且需要以一种非常特殊的方式对通过它们传输的数据进行编码和加帧。协议在中定义


除非你感到难以置信的受虐狂,否则你不想自己去实现它。使用类似于PHP的库来实现WebSocket。

WebSocket不是原始TCP套接字。它们需要一个相当复杂的类似HTTP的握手来建立连接,并且需要以一种非常特殊的方式对通过它们传输的数据进行编码和加帧。协议在中定义


除非你感到难以置信的受虐狂,否则你不想自己去实现它。使用类似于在PHP中实现WebSocket的库。

我也有同样的问题,兄弟,但不需要使用Ratchet或其他库,您可以编写自己的简单代码。握手过程和消息的屏蔽解密相当困难,因此我复制了这些过程的代码

function perform_handshaking($receved_header,$client_conn, $host, $port)
{
    $headers = array();
    $lines = preg_split("/\r\n/", $receved_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')));
    //hand shaking header
    $upgrade  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
    "Upgrade: websocket\r\n" .
    "Connection: Upgrade\r\n" .
    "WebSocket-Origin: $host\r\n" .
    "WebSocket-Location: ws://$host:$port/\r\n".
    "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
    socket_write($client_conn,$upgrade,strlen($upgrade));
    return $upgrade;
}

function unmask($text) {
    $length = ord($text[1]) & 127;
    if($length == 126) {
        $masks = substr($text, 4, 4);
        $data = substr($text, 8);
    }
    elseif($length == 127) {
        $masks = substr($text, 10, 4);
        $data = substr($text, 14);
    }
    else {
        $masks = substr($text, 2, 4);
        $data = substr($text, 6);
    }
    $text = "";
    for ($i = 0; $i < strlen($data); ++$i) {
        $text .= $data[$i] ^ $masks[$i%4];
    }
    return $text;
}

//Encode message for transfer to client.
function mask($text)
{
    $b1 = 0x80 | (0x1 & 0x0f);
    $length = strlen($text);

    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.$text;
}
函数执行握手($recved_header、$client_conn、$host、$port)
{
$headers=array();
$lines=preg\u split(“/\r\n/”,$receved\u头);
foreach($line作为$line)
{
$line=印章($line);
if(preg_match('/\A(\S+):(.*)\z/',$line,$matches))
{
$headers[$matches[1]]=$matches[2];
}
}
$secKey=$headers['Sec-WebSocket-Key'];
$secAccept=base64_编码(包('H*',sha1($secKey.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11'));
//手摇式割台
$upgrade=“HTTP/1.1 101 Web套接字协议握手\r\n”。
“升级:websocket\r\n”。
“连接:升级\r\n”。
“WebSocket来源:$host\r\n”。
“WebSocket位置:ws://$host:$port/\r\n”。
“Sec WebSocket Accept:$secAccept\r\n\r\n”;
socket_write($client_conn,$upgrade,strlen($upgrade));
返回$upgrade;
}
函数取消掩码($text){
$length=ord($text[1])&127;
如果($length==126){
$masks=substr($text,4,4);
$data=substr($text,8);
}
elseif($length==127){
$masks=substr($text,10,4);
$data=substr($text,14);
}
否则{
$masks=substr($text,2,4);
$data=substr($text,6);
}
$text=”“;
对于($i=0;$i=65536)
$header=pack('CCNN',$b1127,$length);
返回$header.$text;
}
代替socket\u accept user socket\u read获取包含来自网页的请求的http头,该网页希望将其http conn升级到websocket,然后使用上面的握手功能写入accept头消息。然后将建立连接。但在客户端,您仍必须添加类似的事件

if("WebSocket" in window){
    var a = "ws://"+serverip+":9000";
    var ws = new WebSocket(a);
    var error = null;

    ws.onopen = function(){
        open();
    }

    ws.onerror = function(err){
        errorhandler(err);

    }
    ws.onmessage = function(e){
        messagehandler(e);

    }
    ws.onclose = function(){
        close();
    }

}

function  open(){
               document.getElementById('logs').innerHTML+='<p>WebSocket Connection OPened</p>';

}

function errorhandler(err){
               document.getElementById('logs').innerHTML+='<p>WebSocket Connection Error occured &nbsp'+err.data+'</p>';

}

function messagehandler(a){
               document.getElementById('logs').innerHTML+="<p>"+a.data+"</p>";

}

function close(){
                document.getElementById('logs').innerHTML+='<p>WebSocket Connection Closed</p>';
                ws = null;

}
if(“窗口中的WebSocket”){
var a=“ws://“+serverip+”:9000”;
var ws=新的WebSocket(a);
var错误=null;
ws.onopen=函数(){
open();
}
ws.onerror=函数(err){
errorhandler(err);
}
ws.onmessage=函数(e){
messagehandler(e);
}
ws.onclose=function(){
close();
}
}
函数open(){
document.getElementById('logs')。innerHTML+='WebSocket连接已打开

'; } 函数errorhandler(err){ document.getElementById('logs')。发生innerHTML+='WebSocket连接错误'+err.data+'

'; } 函数messagehandler(a){ document.getElementById('logs').innerHTML+=“”+a.data+”

”; } 函数关闭(){ document.getElementById('logs').innerHTML+='WebSocket连接已关闭

'; ws=null; }
我也有同样的问题,兄弟,但不需要使用Ratchet或其他库,您可以编写自己的简单代码。握手过程和消息的屏蔽解密相当困难,因此我复制了这些过程的代码

function perform_handshaking($receved_header,$client_conn, $host, $port)
{
    $headers = array();
    $lines = preg_split("/\r\n/", $receved_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')));
    //hand shaking header
    $upgrade  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
    "Upgrade: websocket\r\n" .
    "Connection: Upgrade\r\n" .
    "WebSocket-Origin: $host\r\n" .
    "WebSocket-Location: ws://$host:$port/\r\n".
    "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
    socket_write($client_conn,$upgrade,strlen($upgrade));
    return $upgrade;
}

function unmask($text) {
    $length = ord($text[1]) & 127;
    if($length == 126) {
        $masks = substr($text, 4, 4);
        $data = substr($text, 8);
    }
    elseif($length == 127) {
        $masks = substr($text, 10, 4);
        $data = substr($text, 14);
    }
    else {
        $masks = substr($text, 2, 4);
        $data = substr($text, 6);
    }
    $text = "";
    for ($i = 0; $i < strlen($data); ++$i) {
        $text .= $data[$i] ^ $masks[$i%4];
    }
    return $text;
}

//Encode message for transfer to client.
function mask($text)
{
    $b1 = 0x80 | (0x1 & 0x0f);
    $length = strlen($text);

    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.$text;
}
函数执行握手($recved_header、$client_conn、$host、$port)
{
$headers=array();
$lines=preg\u split(“/\r\n/”,$receved\u头);
foreach($line作为$line)
{
$line=印章($line);
if(preg_match('/\A(\S+):(.*)\z/',$line,$matches))
{
$headers[$matches[1]]=$matches[2];
}
}
$secKey=$headers['Sec-WebSocket-Key'];
$secAccept=base64_编码(包('H*',sha1($secKey.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11'));
//手摇式割台
$upgrade=“HTTP/1.1 101 Web套接字协议握手\r\n”。
“升级:websocket\r\n”。
“连接:升级\r\n”。
“WebSocket来源:$host\r\n”。
“WebSocket位置:ws://$host:$port/\r\n”。
“Sec WebSocket Accept:$secAccept\r\n\r\n”;
socket_write($client_conn,$upgrade,strlen($upgrade));
返回$upgrade;
}
函数取消掩码($text){
$length=ord($text[1])&127;
如果($length==126){
$masks=substr($text,4,4);
$data=substr($text,8);
}
elseif($length==127){
$masks=substr($text,10,4);
$data=substr($text,14);
}
否则{
$masks=substr($text,2,4);
$data=substr($text,6);
}
$text=”“;
对于($i=0$
if("WebSocket" in window){
    var a = "ws://"+serverip+":9000";
    var ws = new WebSocket(a);
    var error = null;

    ws.onopen = function(){
        open();
    }

    ws.onerror = function(err){
        errorhandler(err);

    }
    ws.onmessage = function(e){
        messagehandler(e);

    }
    ws.onclose = function(){
        close();
    }

}

function  open(){
               document.getElementById('logs').innerHTML+='<p>WebSocket Connection OPened</p>';

}

function errorhandler(err){
               document.getElementById('logs').innerHTML+='<p>WebSocket Connection Error occured &nbsp'+err.data+'</p>';

}

function messagehandler(a){
               document.getElementById('logs').innerHTML+="<p>"+a.data+"</p>";

}

function close(){
                document.getElementById('logs').innerHTML+='<p>WebSocket Connection Closed</p>';
                ws = null;

}