【问题标题】:php server socket & webSocket HTML5 clientphp 服务器套接字和 webSocket HTML5 客户端
【发布时间】:2021-10-26 02:02:17
【问题描述】:

我正在尝试将客户端 [webSocket] 与 PHP 服务器套接字连接 我的服务器套接字将接受来自客户端的套接字, 并获取请求标头,

收到请求后,我发回握手 [响应] 但是 webSocket [client] 的状态是 pending 并且永远不会得到响应

JS代码:

      const URL = "ws://localhost:8050";
      var socket = new WebSocket(URL);
    
      socket.onopen = function() {
        console.log("Socket is openned!");
      }
      socket.onmessage = function() {
        console.log("new message!");
      }

和我的 PHP 服务器 Socket:

$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);


    if (socket_bind($this->socket, self::ADDRESS, self::PORT) === false) {
      throw new Exception("Could not bind socket at address ${self::ADDRESS}, port ${self::PORT}");
    }


    if (socket_listen($this->socket) === false) {
      throw new Exception("Could not listen!!");
    }

    $running = true;
    $clients = [];
    while ($running) {

      if (count($clients) < 2) {
        $accept = socket_accept($this->socket);
        // handshake
        $this->handshake($accept);
        $clients[] = $accept;

        sleep(2);
        continue;
      }
    }

握手功能:

  private function handshake($client) {

    if ($client instanceof Socket || is_resource($client)) {
      echo "== Client is Vaild ==\n";
    }

    // client sent the Request
    $read = socket_read($client, 2048);
    if ($read === false) {
      throw new Exception("Could not Read!!");
    }

    // headers
    if (preg_match("/Sec-WebSocket-Key: (.*)/", $read, $matches)){ 

      $key = base64_encode(hash("sha1",$matches[1]."258EAFA5-E914-47DA-95CA-C5AB0DC85B11")); 

      $response_header = "HTTP/1.1 101 Switching Protocols\r\n".
      "Upgrade: websocket\r\n".
      "Connection: Upgrade\r\n".
      "Sec-WebSocket-Accept: $key\r\n";

      // send the response
      $bytes_sent = socket_write($client, $response_header, strlen($response_header));

      if ($bytes_sent === false) {
        echo "\n====== Cannot send the handshake ==========\n";
      } elseif ($bytes_sent > 0) {
        // ------- sent around 155 bytes ----------- //
        echo "\n====== handshake has been sent [". $bytes_sent ."bytes] ==========\n";
      }


    }
  }

发送响应后,客户端仍处于挂起状态, 并且连接没有打开。

谢谢。

客户的要求:

GET / HTTP/1.1
Host: localhost:8050
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36
Upgrade: websocket
Origin: http://localhost
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,ar;q=0.8
Cookie: _ga=GA1.1.213058296.1602471332; __atuvc=1%7C52%2C1%7C3
Sec-WebSocket-Key: UmjWLRlhTXqM1rF6kSaVhQ==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

我正在尝试发回响应:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: NmQwYjVlY2VhMTQzMzUyYjFiNWMwZmU4Y2E3NmFjZTc4ZDc4N2I2Yw==

更新:

  • 我使用 sha1(..., binary = true) 修复了 Sec-WebSocket-Accept 键 在 base64 之前。

  • 结束我的响应我添加了\r\n 来结束标题响应。

现在我收到错误:webSocket 连接 http://host:port 失败。

【问题讨论】:

  • 切换协议后,浏览器在特定端口打开一个新的 TCP 连接,但您的服务器似乎甚至不在那里侦听。我不确定您的网络配置,但我建议使用基于 NODEJS 的套接字解​​决方案,而不是使用 PHP 从头开始​​构建它。也许您的问题是 APACHE/NGINX - 它应该在 webSocket 连接(升级和连接)之前指定特定的标头
  • 感谢您的评论,我知道 NODE js [socket.io ..etc] 或使用 [Firebase..etc],但我想测试我的水平并挑战我自己..

标签: javascript php sockets websocket


【解决方案1】:

搞定了,问题是Sec-WebSocket-Accept键,应该是trim(key)

【讨论】:

    猜你喜欢
    • 2015-10-04
    • 1970-01-01
    • 2014-03-10
    • 2012-01-05
    • 2014-11-05
    • 2018-06-10
    • 1970-01-01
    • 2013-11-11
    • 1970-01-01
    相关资源
    最近更新 更多