DeTechn Blog

PHP原生socket与Websocket握手、解码、加码

<?php
class WsXy{
    public function getHeaders($req)
    {
        $r = $h = $o = null;
        if(preg_match("/GET (.*) HTTP/"   , $req, $match))
            $r = $match[1];
        if(preg_match("/Host: (.*)\r\n/"  , $req, $match))
            $h = $match[1];
        if(preg_match("/Origin: (.*)\r\n/", $req, $match))
            $o = $match[1];
        if(preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $req, $match))
            $key = $match[1];
        return array($r, $h, $o, $key);
    }

    public function wrap($msg="")
    {
        $a = str_split($msg, 125);
        if (count($a) == 1) {
            return "\x81" . chr(strlen($a[0])) . $a[0];
        }
        $ns = "";
        foreach ($a as $o) {
            $ns .= "\x81" . chr(strlen($o)) . $o;
        }
        return $ns;
    }

    public function doHandShake($socket, $buffer)
    {
        $this->log($buffer);
        list($resource, $host, $origin, $key) = $this->getHeaders($buffer);
        //websocket version 13
        $acceptKey = base64_encode(sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));

        $upgrade  = "HTTP/1.1 101 Switching Protocol\r\n" .
            "Upgrade: websocket\r\n" .
            "Connection: Upgrade\r\n" .
            "Sec-WebSocket-Accept: " . $acceptKey . "\r\n\r\n";  //必须以两个回车结尾
        $this->log($upgrade);
        socket_write($socket, $upgrade, strlen($upgrade));
        return true;
    }

    public function unwrap($buffer="")
    {
        $decoded = "";
        $len = ord($buffer[1]) & 127;
        if ($len === 126)  {
            $masks = substr($buffer, 4, 4);
            $data = substr($buffer, 8);
        } else if ($len === 127)  {
            $masks = substr($buffer, 10, 4);
            $data = substr($buffer, 14);
        } else  {
            $masks = substr($buffer, 2, 4);
            $data = substr($buffer, 6);
        }
        for ($index = 0; $index < strlen($data); $index++) {
            $decoded .= $data[$index] ^ $masks[$index % 4];
        }
        return $decoded;
    }

    public function disconnect($clientSocket)
    {
        socket_close($clientSocket);
    }

    public function log($vars)
    {
        var_dump($vars);
    }
}

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »