PHP WebSocketServer可以';t连接到WebKit(Safari)

PHP WebSocketServer可以';t连接到WebKit(Safari),php,webkit,websocket,handshake,Php,Webkit,Websocket,Handshake,我用PHP编写了一个WebSocket服务器,它可以很好地连接到Firefox,但不能连接到Safari。我想,握手有问题。Safari需要旧版的hybi00。。。但我找不到错误:/ 尝试连接后,Safari中的连接直接关闭。 提前感谢您的帮助 <?php error_reporting(E_ALL); set_time_limit(0); date_default_timezone_set("Europe/Berlin"); ob_implicit_flush(true); funct

我用PHP编写了一个WebSocket服务器,它可以很好地连接到Firefox,但不能连接到Safari。我想,握手有问题。Safari需要旧版的hybi00。。。但我找不到错误:/

尝试连接后,Safari中的连接直接关闭。 提前感谢您的帮助

<?php
error_reporting(E_ALL);
set_time_limit(0);
date_default_timezone_set("Europe/Berlin");
ob_implicit_flush(true);

function debug($text)
{
    $file = "log.html";
    file_put_contents($file,
    "<pre>".$text."</pre>"."<b>Ende der Information</b><p />", 8);
}



//Socket initialisieren
$master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($master, SOL_SOCKET, SO_REUSEADDR, 1);
//An diesen Computer binden
socket_bind($master, "localhost", 10000) or die();
//Maximale Verbindungsanforderungen: 5
socket_listen($master, 5);

do
{
    $client = socket_accept($master);
    echo "Neuer Client!\n";
    new Client($client);
} while(true);

exit();





//Clientklasse
class Client
{
    private $connection;
    private $header = array();
    private $crypt; //BOOL, hybi00 needs no en-/decryption but hybi06+

    function __construct(&$socket)
    {
        $this->connection = $socket;
        $this->SetWebSecKey();

        while(true)
        {
            $q = socket_read($this->connection, 1024);
            if(isset($q))
            {
                echo $this->unmask($q);
            }
            $welcome = "\x81\x8c\xff\xb8\xbd\xbd\xb7\xdd\xd1\xd1\x90\x98\xea\xd2\x8d\xd4\xd9\x9c";
        }
    }

    /**
     * Unmask a received payload
     * @param $payload
     * 
     * http://srchea.com/blog/2011/12/build-a-real-time-application-using-html5-websockets/
     */
    private 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;
    }

    /**
    * Encode a text for sending to clients via ws://
    * @param $text
    * 
    * http://srchea.com/blog/2011/12/build-a-real-time-application-using-html5-websockets/
    */
    private 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;
    }

    private function SetWebSecKey()
    {
        //Headerrequest in Array teilen
        $request = socket_read($this->connection, 1024);
        $request = explode("\n", $request);
        foreach($request as $key=>$head)
        {
            $header = explode(":", $head, 2);
            $header[0] = trim($header[0]); //Parameter
            $header[1] = trim($header[1]); //Wert

            $this->header[$header[0]] = $header[1];
        }

        $handshake = new Handshake($this->header);
        $handshake->Send($this->connection);
    }

    private function SendPlain($text)
    {
        socket_write($this->connection, $text, strlen($text));
    }
}

class Handshake
{
    private $header;
    private $hybi00;
    private $secKey;

    public function __construct($headerArray)
    {
        echo "\nHandshake wird ausgeführt: ";
        //Einfacher oder doppelter SecWebKey?
        //Einfach: Hybi06+
        //Doppelt: Hybi00+
        $this->header = $headerArray;
        if(isset($this->header["Sec-WebSocket-Key"]))
        {
            echo "Hybi06+\n";
            //Moderner Hybi06+
            $this->secKey = $this->InitHybi06();
        } elseif(isset($this->header["Sec-WebSocket-Key1"])) {
            //Älterer Hybi00+
            echo "Hybi00+\n";
            $this->secKey = $this->InitHybi00();
        } else {
            echo "Fehler - Unbekanntes WebSocket-Protokoll\n";
            return;
        }
    }

    private function InitHybi06()
    {
        $this->hybi00 = false;

        $key = $this->header["Sec-WebSocket-Key"];

        $GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
        $key .= $GUID;

        return base64_encode(sha1($key, true));
    }

    private function InitHybi00()
    {
        $this->hybi00 = true;

        $key1 = $this->header["Sec-WebSocket-Key1"];
        $key2 = $this->header["Sec-WebSocket-Key2"];

        $key1 = $this->Hybi00NumSpace($key1);
        $key2 = $this->Hybi00NumSpace($key2);

        $data = array_keys($this->header);
        $data = $data[count($this->header)-1];

        $ctx = hash_init('md5');
        hash_update($ctx, pack("N", $key1));
        hash_update($ctx, pack("N", $key2));
        hash_update($ctx, $data);
        $hash_data = hash_final($ctx,true);

        return $hash_data;
    }

    private function Hybi00NumSpace($key)
    {
        $numbrs = preg_replace('/[^\d]*/', '', $key);
        $spaces = strlen(preg_replace('/[^\s][^\s]*/', '', $key));

        return $numbrs/$spaces;
    }

    public function Send($socket, $origin="http://localhost", $location="ws://localhost", $return=false)
    {
        if(!isset($this->header) || !isset($this->hybi00) || !isset($this->secKey))
        {
            echo "Fehler: Handshake nicht vollständig!\n"; return;
        }
        $header = $this->CreateHeader($origin, $location);
        debug($header);
        $header = explode("\n", $header);
        if($return)
            return $header;
        foreach($header as $line)
        {
            $line .= "\n";
            socket_write($socket, $line, strlen($line));
        }
    }

    private function CreateHeader($origin, $location)
    {
        $header = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n".
        "Upgrade: WebSocket\r\n".
        "Connection: Upgrade\r\n".
        "Sec-WebSocket-Origin: $origin\r\n";

        if($this->hybi00)
        {
            $header .= "Sec-WebSocket-Location: $location\r\n";
            $header .= "\r\n".$this->secKey.chr(0);
        } else {
            $header .= "Sec-WebSocket-Accept: ".$this->secKey."\r\n\r\n";
        }

        return $header;
    }
}

我不知道如何在你的代码中做到这一点,你可以看看-它的非阻塞服务器在php上编写,支持websocket。

我不知道如何在你的代码中做到这一点,你可以看看-它的非阻塞服务器在php上编写,支持websocket。

获取wireshark并将你的服务器的行为与正常工作的服务器进行比较“服务器“它本身运行正常,并从Safari和Firefox接收头文件,但它无法发送到Safari,而FF没有问题。没有机会。我必须安装node.js。我想写我自己的回复。我要求的是一个可编程的解决方案,而不是第二台Web服务器上的现成框架。获取wireshark并将您的服务器的行为与工作服务器进行比较。“服务器”本身运行正常,并从Safari和Firefox接收头文件-但它无法发送到Safari,而FF没有问题。不可能。我必须安装node.js。我想写我自己的回复。我要求的是一个可编程的解决方案,而不是第二台Web服务器上的现成框架。