Michael
Michael

Reputation: 423

Make a PHP socket server for WebSocket [handshake]

I try to make my own PHP socket Server in order to work with HTML5 WebSocket API, but i can not do the handshake step, i read the [rfc6455][1] here my PHP Server code :

Here the Javascript code :

var socket = new WebSocket("ws://127.0.0.1:1577/server.php");

socket.onopen = function (e) {
    console.log("openned : "+e.readyState);
}
socket.onclose = function (e) {
    console.log("Socket connection closed : "+e);
}

Here the PHP code :

<?php

set_time_limit(0);
$adr = "127.0.0.1";
$port = 1577;
 
$m_sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$msg = "Welcome...";
$cls = array();
 
socket_bind($m_sock, $adr, $port);
socket_listen($m_sock, 5);
echo "Server start...\n\n";

do{
        $msgsock = socket_accept($m_sock);
 
        array_push($cls, $msgsock);
        echo "Connected...\n\n";
        usleep(100);
        //socket_write($msgsock, $msg, strlen($msg)); //this is the 'bug'
        do{
                if (false === ($buf = socket_read($msgsock, 2048, PHP_NORMAL_READ))) {
                   echo "socket_read() fail :" . socket_strerror(socket_last_error($msgsock)) . "\n";
                    break 2;
                }
                if(preg_match("/Sec-WebSocket-Key: (.*)/",$buf,$match)){ 
                        $key =  base64_encode(hash("sha1",trim($match[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\r\n";

                        //SERVER RESPONSE ----
                        socket_write($msgsock,$response_header,strlen($response_header));

                        echo "handshake done...";
                };
        } while(1);
        socket_close($msgsock);
} while(1);

i always have this error : failed: Error during WebSocket handshake: Invalid status line [1]: https://www.rfc-editor.org/rfc/rfc6455

Here the HTTP request :

the HTTP request :

Accept-Encoding:gzip, deflate, sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,he;q=0.2
Cache-Control:no-cache
Connection:Upgrade
Cookie:__utma=96992031.134451192.1399804258.1402844967.1402848436.4; __utmz=96992031.1399804258.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); _ga=GA1.4.134451192.1399804258; toolbarDisplay=hide
Host:127.0.0.1:1577
Origin:http://127.0.0.1
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:2yODScjZV/dap0DsDSWDFQ==
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36

Here the reponse generated by the PHP server :

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

Upvotes: 4

Views: 7300

Answers (3)

user12179366
user12179366

Reputation: 68

Just add a third parameter 'true' in your hash function call. so it will looks like this :

hash("sha1",trim($match[1])."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true)

For more informations PHP Hash Function

Upvotes: 0

Steve Zachmann
Steve Zachmann

Reputation: 1

Just by looking at the response it appears like your websocket accept looks wrong, it looks like it's too long. I know this because I had the exact same problem. If it's the same problem I had, here's the issue:

SHA-1 passes back a hexadecimal value. This value CANNOT simply converted to base64, as is. The hex value must first be converted to ascii text, and then the ascii text value can be base64 encoded.

The simple answer here is to simply take the hex value passed back from SHA-1 and break it into chunks of 2 characters. Take those 2 characters, convert them to normal decicmal numbers and then do a look-up to what ascii character code the number corresponds too.

Upvotes: 0

Endel Dreyer
Endel Dreyer

Reputation: 1654

You can read the source-code of Ratchet and see how they've done.

There is a class which implements the handshake here.

Upvotes: 1

Related Questions