我正在尝试设置一个 WebSocket 应用程序,但我陷入了以下困境。接受套接字后,我按预期收到了客户端的标头,但是当我尝试将升级发送回时socket_write()
会引发警告:
Warning: socket_write(): unable to write to socket [10038]: An operation was attempted on something that is not a socket
这发生在以下代码中:
var_dump($this->socket); //output: resource(2) of type (Socket)
socket_write($this->socket, $upgrade);
这发生在 pthreads 上下文中。
PHP向我抛出此警告的可能原因是什么?
完整代码:
public function handshake($headers)
{
Main::console($headers);
Main::console("Getting client WebSocket version...");
Main::console("Headers: \r\n\r\n".$headers);
if(preg_match("/Sec-WebSocket-Version: (.*)\r\n/", $headers, $match))
$version = $match[1];
else {
Main::console("The client doesn't support WebSocket");
return false;
}
Main::console("Client WebSocket version is {$version}, (required: 13)");
if($version == 13) {
// Extract header variables
Main::console("Getting headers...");
if(preg_match("/GET (.*) HTTP/", $headers, $match))
$root = $match[1];
if(preg_match("/Host: (.*)\r\n/", $headers, $match))
$host = $match[1];
if(preg_match("/Origin: (.*)\r\n/", $headers, $match))
$origin = $match[1];
if(preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $headers, $match))
$key = $match[1];
Main::console("Client headers are:\r\n\r\n".
"- Root: ".$root."\r\n".
"- Host: ".$host."\r\n".
"- Origin: ".$origin."\r\n".
"- Sec-WebSocket-Key: ".$key."\n");
Main::console("Generating Sec-WebSocket-Accept key...");
$acceptKey = $key.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
$acceptKey = base64_encode(sha1($acceptKey, true));
$upgrade = "HTTP/1.1 101 Switching Protocols\r\n".
"Upgrade: websocket\r\n".
"Connection: Upgrade\r\n".
"Sec-WebSocket-Accept: $acceptKey".
"\r\n\r\n";
Main::console("Sending this response to the client #{$this->getId()}:\r\n\r\n".$upgrade);
var_dump($this->socket);
socket_write($this->socket, $upgrade, strlen($upgrade));
$this->setHandshake(true);
Main::console("Handshake is successfully done!");
return true;
}
else {
Main::console("WebSocket version 13 required (the client supports version {$version})");
return false;
}
}
public function run()
{
while($this->alive)
{
$bytes = @socket_recv($this->socket, $buffer, 4096, MSG_WAITALL);
if ($buffer)
{
if(!$this->handshake)
{
$this->handshake($buffer);
} else {
Main::console("Client {$this->getID()} says {$buffer}");
}
}
}
}