websocket Error during WebSocket handshake: net :: ERR_INVALID_HTTP_RESPONSE

0

I'm having problems implementing websocket with php socket, I'm testing my machine but I can not find the problem and I'm already circling around. server     

set_time_limit(0);

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

if (socket_bind($socket, $ip, $puerto) === false) {
    echo "socket_bind() falló: razón: " . socket_strerror(socket_last_error($sock)) . "\n";
}

if (socket_listen($socket, 5) === false) {
    echo "socket_listen() falló: razón: " . socket_strerror(socket_last_error($sock)) . "\n";
}

while (true) {
    if (($newc = socket_accept($socket)) !== false) {
        echo "Client $newc has connected\n";
//        $clients[] = $newc;
        // leemos la informacion que nos envian
        $input = socket_read($newc, 1024);
        echo preg_replace("[ \t\r\n]", "", $input);

        $msg = "Hello Client!\r\n";
        socket_write($newc, $msg, strlen($msg));
        socket_close($newc);
    }
}

socket_close($socket);

customer

<?php require_once ('config.php');?>
<!DOCTYPE html>
<meta charset="utf-8" />
<title>WebSocket Test</title>
<script src="jquery.js" type="text/javascript"></script>
<script language="javascript" type="text/javascript">
    window.onload = function () {
        var websocket = new WebSocket('<?php echo "ws://{$ip}:{$puerto}"; ?>');

        websocket.onopen = function (evt) {
            websocket.send('Hello Server!');
        };
        websocket.onclose = function (evt) {
            console.log("websocket close");
        };
        websocket.onmessage = function (evt) {
            console.log(event.data);
        };
        websocket.onerror = function (evt) {
            console.log(event.data);
        };
    };
</script>
<h2>WebSocket Test</h2>

Inside the red box shows the browser header and the blue box the php client with socket_connect ()

According to the tests performed, I understand that it is not a server problem. But the browser keeps sending me this error

  

failed: Error during WebSocket handshake:   net :: ERR_INVALID_HTTP_RESPONSE

    
asked by Richard Collao Olivares 02.11.2018 в 18:51
source

1 answer

0

I have partially solved the problem of the connection by adding the corresponding handshake, however the messages arrive with strange characters when I use websocket, but not with other clients.

<?php

class MySocketServer {

    protected $socket;
    protected $clients = [];
    protected $changed;

    public function __construct($host, $port) {
        set_time_limit(0);
        $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
                or die("error: " . socket_strerror(socket_last_error()));
        socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, 1);
        //bind socket to specified host
        socket_bind($this->socket, $host, $port)
                or die("error: " . socket_strerror(socket_last_error(socket_last_error($this->socket))));
        //listen to port
        socket_listen($this->socket)
                or die("error: " . socket_strerror(socket_last_error(socket_last_error($this->socket))));
    }

    public function __destruct() {
        foreach ($this->clients as $client) {
            socket_close($client);
        }
        socket_close($this->socket);
    }

    public function run() {
        // create a list of all the clients that will be connected to us..
        // add the listening socket to this list
        $this->clients = array($this->socket);
        while (true) {
            // create a copy, so $clients doesn't get modified by socket_select()
            // reset changed
            $this->changed = $this->clients;

            // get a list of all the clients that have data to be read from
            // if there are no clients with data, go to next iteration
            $write = $except = NULL;
            if (socket_select($this->changed, $write, $except, 0) > 0) {
                $this->checkNewClients();
                $this->checkMessageRecieved();
                $this->checkDisconnect();
            }
        }
    }

    private function checkNewClients() {
        $this->log("checkNewClients...");

        // check if there is a client trying to connect
        if (in_array($this->socket, $this->changed)) {
            // accept the client, and add him to the $clients array
            $this->clients[] = $newsock = socket_accept($this->socket);

            // $header = socket_read($newsock, 2048, PHP_NORMAL_READ);
            // @socket_recv($newsock, $header, 1024, 0);
            if ((int) @socket_recv($newsock, $header, 2048, MSG_DONTWAIT) > 0) {
                $handshake = $this->handshake($header);
                $this->log("handshake: " . $handshake);
                socket_write($newsock, $handshake, strlen($handshake));
            }

            socket_getpeername($newsock, $ip);
            $this->log("There are " . (count($this->clients) - 1) . " client(s) connected to the server\n");
            $this->log("New client connected: " . $ip);

            // remove the listening socket from the clients-with-data array
            $key = array_search($this->socket, $this->changed);
            unset($this->changed[$key]);
        }
    }

    private function checkMessageRecieved() {
        foreach ($this->changed as $key => $socket) {
            $buffer = null;
            while (socket_recv($socket, $buffer, 1024, 0) > 0) {
                $this->log(trim("Client Message: " . $buffer));
                unset($this->changed[$key]);
                break;
            }
        }
    }

    private function checkDisconnect() {
        foreach ($this->changed as $changed_socket) {
            $buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ);
            if ($buf !== false) {
                continue;
            }
            // remove client for $clients array
            $found_socket = array_search($changed_socket, $this->clients);
            socket_getpeername($changed_socket, $ip);
            unset($this->clients[$found_socket]);
            $this->log('client ' . $ip . ' has disconnected');
        }
    }

    function handshake($header) {
        $handshake = '';
        $this->log('header ' . $header);
        if (preg_match("/Sec-WebSocket-Version: (.*)\r\n/", $header, $match)) {
            $version = $match[1];
        } else {
            $this->log("The client doesn't support WebSocket");
        }

        if ($version == 13) {
            if (preg_match("/GET (.*) HTTP/", $header, $match))
                $root = $match[1];
            if (preg_match("/Host: (.*)\r\n/", $header, $match))
                $host = $match[1];
            if (preg_match("/Origin: (.*)\r\n/", $header, $match))
                $origin = $match[1];
            if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $header, $match))
                $key = $match[1];

            $acceptKey = $key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
            $acceptKey = base64_encode(sha1($acceptKey, true));

            $handshake .= "HTTP/1.1 101 Switching Protocols\r\n" .
                    "Upgrade: websocket\r\n" .
                    "Connection: Upgrade\r\n" .
                    "Sec-WebSocket-Accept: $acceptKey" .
                    "\r\n\r\n";
        } else {
            $this->log("WebSocket version 13 required (the client supports version {$version})");
        }
        return $handshake;
    }

    private function sendMessage($msg) {
        foreach ($this->clients as $client) {
            socket_write($client, $msg, strlen($msg));
        }
        return true;
    }

    private function log($msg) {
        echo "\r\n$msg\r\n";
    }

}

require_once ('config.php');
(new MySocketServer($host, $port))->run();
    
answered by 04.11.2018 в 02:02