PHP WebSocketServer可以';t连接到WebKit(Safari)
我用PHP编写了一个WebSocket服务器,它可以很好地连接到Firefox,但不能连接到Safari。我想,握手有问题。Safari需要旧版的hybi00。。。但我找不到错误:/ 尝试连接后,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
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服务器上的现成框架。