0

What I'm trying is connect the client [webSocket] with PHP server socket. My server socket will accept the socket from client, and fetch the Request headers.

After receiving the request, I sent back handshake [response]. But the status for webSocket [client] is pending and never gets the response.

JS code:

  const URL = "ws://localhost:8050";
  var socket = new WebSocket(URL);

  socket.onopen = function() {
    console.log("Socket is opened!");
  }
  socket.onmessage = function() {
    console.log("new message!");
  }

And this is my PHP server 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;
      }
    }

handshake function:

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


    }
  }

After sending the response, the client still in pending status, and the connection not opened.

Thank you.

The Request From Client:

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

what i'm trying is sending back the response:

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

UPDATE

  • I fixed the Sec-WebSocket-Accept key by using sha1(..., binary = true) before base64.

  • End my response I added \r\n to end the header response.

Now I'm getting error:

webSocket connection http://host:port failed.

2
  • After switching protocol, the browser open a new TCP connection at a specific port, but it seems like your server doesn't even listens there. I'm not sure about your network configuration , but I would've suggest using NODEJS based socket solutions, than building this from scratch with PHP. Maybe your problem is the APACHE/NGINX - that should specify specific headers prior the webSocket connection(Upgrade, and Connection) Commented Aug 26, 2021 at 17:54
  • Thank you for your comment, i know about NODE js [socket.io ..etc] or using [Firebase..etc], but i want to test my level and challenge my self.. Commented Aug 26, 2021 at 18:21

1 Answer 1

1

It's done, the problem was Sec-WebSocket-Accept key, it needed to be trim(key)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.