Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何修复Websocket握手代码?_Php_Google Chrome_Websocket_Phpwebsocket - Fatal编程技术网

Php 如何修复Websocket握手代码?

Php 如何修复Websocket握手代码?,php,google-chrome,websocket,phpwebsocket,Php,Google Chrome,Websocket,Phpwebsocket,这可能是一个熟悉的悲伤故事。但是有这么多的人在那里,我是这样一个n00b我找不到答案,所以如果你能帮助我,我希望你的帮助 所以,我使用的是lemmingzshadow的phpwebsocket(如果您不熟悉,谷歌会很容易地提供)。据我所知,他推出的版本有一个bug,它不符合Chrome 20+现在使用的标准。这和握手和安全钥匙有关,但这正是我要解决的问题。我知道我需要根据其他问题提供以下信息,希望您能帮助我理解并解决此问题: Chrome接收到的标题已编辑(显然,我已将消息发布到服务器两次):

这可能是一个熟悉的悲伤故事。但是有这么多的人在那里,我是这样一个n00b我找不到答案,所以如果你能帮助我,我希望你的帮助

所以,我使用的是lemmingzshadow的phpwebsocket(如果您不熟悉,谷歌会很容易地提供)。据我所知,他推出的版本有一个bug,它不符合Chrome 20+现在使用的标准。这和握手和安全钥匙有关,但这正是我要解决的问题。我知道我需要根据其他问题提供以下信息,希望您能帮助我理解并解决此问题:

Chrome接收到的标题已编辑(显然,我已将消息发布到服务器两次):

我的服务器收到的标头为:

Upgrade: websocket
Connection: Upgrade
Host: gumonshoe.net:8000
Origin: http://gumonshoe.net
Sec-WebSocket-Key: v3+iw0U78qkwZnp+RWTu3A
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
我不认为这些饼干是必要的,但如果我错了,请纠正我

我不想做下一部分,但我认为粘贴它总比什么都不做,需要以后再回来要好。下面是读取和解释握手并发送新握手的代码部分

欢迎您的帮助:

<?PHP
private function handshake($data)
    {   
        $this->log('Performing handshake\r\n\r\n' . $data);  
        $lines = preg_split("/\r\n/", $data);

        // check for valid http-header:
        if(!preg_match('/\AGET (\S+) HTTP\/1.1\z/', $lines[0], $matches)) {
            $this->log('Invalid request: ' . $lines[0]);
            $this->sendHttpResponse(400);
            stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
            return false;
        }

        // check for valid application:
        $path = $matches[1];
        $this->application = $this->server->getApplication(substr($path, 1));
            if(!$this->application) {
                $this->log('Invalid application: ' . $path);
                $this->sendHttpResponse(404);           
                stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
                $this->server->removeClientOnError($this);
                return false;
            }

        // generate headers array:
        $headers = array();
        foreach($lines as $line)
        {
            $line = chop($line);
            if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
            {
                $headers[$matches[1]] = $matches[2];
            }
        }

        // check for supported websocket version:       
        if(!isset($headers['Sec-WebSocket-Version']) || $headers['Sec-WebSocket-Version'] < 6)
        {
            $this->log('Unsupported websocket version.');
            $this->sendHttpResponse(501);
            stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
            $this->server->removeClientOnError($this);
            return false;
        }

        // check origin:
        if($this->server->getCheckOrigin() === true)
        {
            $origin = (isset($headers['Sec-WebSocket-Origin'])) ? $headers['Sec-WebSocket-Origin'] : false;
            $origin = (isset($headers['Origin'])) ? $headers['Origin'] : $origin;
            if($origin === false)
            {
                $this->log('No origin provided.');
                $this->sendHttpResponse(401);
                stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
                $this->server->removeClientOnError($this);
                return false;
            }

            if(empty($origin))
            {
                $this->log('Empty origin provided.');
                $this->sendHttpResponse(401);
                stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
                $this->server->removeClientOnError($this);
                return false;
            }

            if($this->server->checkOrigin($origin) === false)
            {
                $this->log('Invalid origin provided. : ' . $origin . ' Legal options were:');
                $gumk = 0;
                foreach(array_keys($this->server->getAllowedOrigins()) as $lo) {
                    $this->log( '[' . $gumk++ . '] : ' . $lo);
                }
                $this->sendHttpResponse(401);
                stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
                $this->server->removeClientOnError($this);
                return false;
            }
        }       

        // do handyshake: (hybi-10)
        $secKey = $headers['Sec-WebSocket-Key'];
        $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
        $response = "HTTP/1.1 101 Switching Protocols\r\n";
        $response.= "Upgrade: websocket\r\n";
        $response.= "Connection: Upgrade\r\n";
        $response.= "Sec-WebSocket-Accept: " . $secAccept . "\r\n";
        $response.= "Sec-WebSocket-Protocol: " . substr($path, 1) . "\r\n\r\n";     
        if(false === ($this->server->writeBuffer($this->socket, $response)))
        {
            return false;
        }
        $this->handshaked = true;
        $this->log('Handshake sent');
        $this->application->onConnect($this);

        // trigger status application:
        if($this->server->getApplication('status') !== false)
        {
            $this->server->getApplication('status')->clientConnected($this->ip, $this->port);
        }

        return true;            
    }

由于我在这一级别的服务器调试方面基本上缺乏经验,如果能给出比将我与文档/规范联系起来更详细的答案,我将不胜感激。

如果你们中的任何一位正在碰壁,这就是令人不快的代码:

$response.= "Sec-WebSocket-Protocol: " . substr($path, 1) .
我确信有一种方法可以实际设置所需/可能的协议,但我还不确定它们是什么;我不确定这对我来说是否必要。如果有人对协议交换的用途有解释,我很想读一下,但现在我只是把它从我的代码中去掉

大量的谷歌搜索来发现这个小问题


我也在握手中丢弃了pack(H*)代码,根据我所读的内容,这似乎是不必要的。我不确定这是否有任何作用,但没有必要让程序运行。

哦,还有错误,/:WebSocket握手时出错:Sec WebSocket协议不匹配WebSocket使用HTTP握手的外表,但不是HTTP协议,这就是为什么您的bowser请求升级到web套接字协议。从这里开始,安全令牌用于确保客户端和服务器确实是websocket服务器和客户端,而不是偶然出现的浏览器。这对我来说是有意义的。没有的部分是“Sec WebSocket协议”,它显然是有用的;我只是不确定它什么时候合适,以及在客户端使用该开关时必须做什么。
Sec-
头不能由用户代理使用JavaScript设置。这是一个安全问题,它确保WebSocket不会被XSS攻击破坏。我想我应该解释的另一件事是,
WebSocket协议
只是说嘿,我知道这些版本的WebSocket协议,所以你可以在这些版本中与我交谈。好吧,酷。所以,因为我控制了两个端点,所以这并不重要。谢谢此外,XSS的事情是有意义的,因为我有一种想法,这是很容易哄骗一些人在中间攻击,除非你添加一个额外的层自己的加密。操作客户端似乎也不难,所以我不是在抱怨,只是集体文档在这一点上不清楚。
Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch
$response.= "Sec-WebSocket-Protocol: " . substr($path, 1) .