如何解决Websocket握手代码?

问题描述:

这可能是一个熟悉的哭泣故事。但是那里有很多人,我很难找到答案,所以如果你能帮助我,我希望你的帮助。如何解决Websocket握手代码?

所以,我使用lemmingzshadow phpwebsocket(如果你不熟悉,谷歌会很容易地把它带出来)。据我可以告诉他的版本,他有一个错误,它不符合Chrome 20. +现在使用的标准。它与安全密钥的手摇&有关,但这是我坚持的地方。我知道我需要在以下基础上其他问题提供,希望你能帮助我了解和解决这个问题:(编辑;我显然张贴的消息发送到服务器的两倍)

Chrome的接收是标题:

HTTP/1.1 101 Switching Protocols 
Upgrade: websocket 
Connection: Upgrade 
Sec-WebSocket-Accept: aWXrpLOnEm15mE8+w1zG05ad01k= 
Sec-WebSocket-Protocol: QuatroDuo 

我的服务器收到标题是:

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 

我不认为cookies是必要的,纠正我,如果我错了,虽然。

我讨厌做下一部分,但我认为这一切都比无所事事,需要稍后再回来更好。这里是代码的一部分,它读取&来解释握手并发送新握手。

帮助是appreaciated:

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

接收以下错误,

Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch 

正如我在这个级别的服务器调试主要是缺乏经验的,更详细的回答不是链接我的文档/规格将不胜感激。

+0

噢,和错误,/:在WebSocket握手期间错误:Sec-WebSocket协议不匹配 – Kirk 2012-07-10 03:25:40

如果你们都跳动你的头撞墙,这是有问题的代码:

$response.= "Sec-WebSocket-Protocol: " . substr($path, 1) . 

我肯定有实际设置所需/可能协议的方式,但我我不确定他们是什么;我不确定它是否适合我的目的。如果有人解释了协议切换的内容,我很乐意阅读它,但现在我只是把它从我的代码中删除。

很多谷歌搜索找到这个小问题。

我还根据我正在阅读的内容,在握手过程中丢弃了包(H *)代码,这似乎并不必要。我不确定这是否做了什么,但没有必要让程序运行。

+0

Websockets使用HTTP握手的单板,但不是HTTP协议,这就是为什么你的bowser请求升级到Web套接字协议。从那里安全令牌用来确保客户端和服务器确实是websocket服务器和客户端,而不是偶然出现的浏览器。 – 2012-07-10 05:11:38

+1

这对我有意义。不是“Sec-WebSocket-Protocol”的部分。这显然是有用的;我只是不确定什么时候它的合适以及我在客户端必须做什么才能开始使用该开关。 – Kirk 2012-07-10 13:34:28

+0

'Sec-'标头不能由使用JavaScript的User-Agent设置。这是一件安全的事情,它确保WebSocket不会受到XSS攻击的危害。 – 2012-07-10 16:34:10