0

I found some script on the internet. I've tried to configure it, but it doesn't work for me. I added it, I'm not too knowledgeable with the websocket functions, so please help me, if you can! When I tried to send a message to the server, I always get the same error code:

"InvalidStateError: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state."

The script doesn't product the else what includes this comment:

// clients who are connected with server will enter into this case

// first client will handshake with server and then exchange data with server

I don't know why, but I really would like to understand this stuff. Can help me someone? (The handshake is OK. If it was not be OK, I would get a javascript error. )

<?php

error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();

$address = "127.0.0.1";
$port = "1234";

GLOBAL $clients;
GLOBAL $client_list;

// socket creation
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);

if (!is_resource($socket))
    console("socket_create() failed: ".socket_strerror(socket_last_error()), true);

if (!socket_bind($socket, $address, $port))
    console("socket_bind() failed: ".socket_strerror(socket_last_error()), true);

if(!socket_listen($socket, 20))
    console("socket_listen() failed: ".socket_strerror(socket_last_error()), true);

console("Server started on $address : $port\n\n");
$master = $socket;
$sockets = array($socket);
$counert = 0;
while(true) {
    $changed = $sockets;
    foreach($changed as $socket) {
        if($socket == $master) {
            $log = "Egyenlők!";
        } else {
            $log = "Nem egyenlők!";
        }
        //console($log);
        if($socket == $master) {
            // new client will enter in this case and connect with server
            socket_select($changed,$write=NULL,$except=NULL,NULL);
            console("Master Socket Changed.\n\n");
            $client = socket_accept($master);
            if($client < 0) {
                console("socket_accept() failed\n\n"); 
                continue; 
            } else {
                console("Connecting socket.\n\n");
                fnConnectacceptedSocket($socket,$client); $master=null;
            }
        } else {
            // clients who are connected with server will enter into this case
            // first client will handshake with server and then exchange data with server
            
        $client = getClientBySocket($socket);
            if($client) {
                if ($clients[$socket]["handshake"] == false) {
                    $bytes = @socket_recv($client, $data, 2048, MSG_DONTWAIT);
                    if ((int)$bytes == 0)
                        continue;
                        console("Handshaking headers from client:".$data);
                    if (handshake($client, $data, $socket))
                        $clients[$socket]["handshake"] = true;
                    } else if ($clients[$socket]["handshake"] == true) {
                        $bytes = @socket_recv($client, $data, 2048, MSG_DONTWAIT);
                    if ($data != "") {
                        $decoded_data = unmask($data);
                        socket_write($client, encode("You have entered: ".$decoded_data));
                        console("Data from client:".$decoded_data);
                        socket_close($socket);
                    }
                }
            }
        }
    }
}

# Close the master sockets
socket_close($socket);

function unmask($payload) {
    $length = ord($payload[1]) & 127;

    if($length == 126) {
        $masks = substr($payload, 4, 4);
        $data = substr($payload, 8);
    }
    elseif($length == 127) {
        $masks = substr($payload, 10, 4);
        $data = substr($payload, 14);
    }
    else {
        $masks = substr($payload, 2, 4);
        $data = substr($payload, 6);
    }

    $text = '';
for ($i = 0; $i < strlen($data); ++$i) {
        $text .= $data[$i] ^ $masks[$i%4];
    }
    return $text;
}

function encode($text) {
    // 0x1 text frame (FIN + opcode)
    $b1 = 0x80 | (0x1 & 0x0f);
    $length = strlen($text);

    if($length <= 125)      
        $header = pack('CC', $b1, $length);     
    elseif($length > 125 && $length < 65536) 
        $header = pack('CCS', $b1, 126, $length);   
    elseif($length >= 65536)
        $header = pack('CCN', $b1, 127, $length);

    return $header.$text;
}

function fnConnectacceptedSocket($socket, $client) {
    GLOBAL $clients;
    GLOBAL $client_list;
    $clients[$socket]["id"] = uniqid();
    $clients[$socket]["socket"] = $socket;
    $clients[$socket]["handshake"] = false;
    console("Accepted client \n\n");
    $client_list[$socket] = $client;
}

function getClientBySocket($socket) {
    GLOBAL $client_list;
    return $client_list[$socket];
}

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

    if($version == 13) {
        // Extract header variables
    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];

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

        socket_write($client, $upgrade);
        return true;
    }
    else {
        console("WebSocket version 13 required (the client supports version {$version})");
        return false;
    }
}

function console($text) {
    $text = $text . "\r\n";
    $File = "log.txt"; 
    $Handle = fopen($File, 'a');
    fwrite($Handle, $text); 
    fclose($Handle);
}

?>

And this is the javascript code:

<script>
var socket;
var host = "ws://localhost:1234/chat/server.php";
function init() {
  try {
    socket = new WebSocket(host);
    //log('WebSocket - status '+socket.readyState);
    socket.onopen    = function(msg){ socket.send("asdf"); log("Welcome - status "+this.readyState); };
    socket.onmessage = function(msg){ log("Received: "+msg.data); };
    socket.onclose   = function(msg){ log("Disconnected - status "+this.readyState); };
  }
  catch(ex){ log(ex); }
  $("msg").focus();
}

function send() {
    var txt,msg;
    txt = $("msg");
    msg = txt.value;
    if(!msg){ alert("Message can not be empty"); return; }
    txt.value="";
    txt.focus();
    try{ socket.send(msg); log('Sent: '+msg); } catch(ex){ log(ex); }
}
function quit(){
    log("Goodbye!");
    socket.close();
    socket=null;
}

// Utilities
function $(id){ return document.getElementById(id); }
function log(msg){ $("log").innerHTML+="\n"+msg; }
function onkey(event){ if(event.keyCode==13){ send(); } }
</script>

1 Answer 1

1

How are you running the PHP code exactly? I tested it and at least something is happening here :). I'm not sure using PHP to implement a websocket server is the way to go though!

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

3 Comments

Web Workers would be better with NodeJS , as it allows multiple threads and is better suited to web applications requiring a live connection. A hanging PHP script can create a number of problems.
I have a wamp server, and my scripts is in the subfolder of www library. I have a server.php script, and an index.php. The index.php includes the javascript code, the server.php includes the php code.
Yes, it won't work through a WAMP server. Normally Apache sits between (HTTP) requests and your PHP code. But since you are dealing with sockets directly, you have to run PHP as an application, e.g. through the php command and let it handle incoming connections on its own. I want to add the PHP is in 99% cases ran through a web server such as Apache, implementing websockets like this is most probably not a good idea if used for anything other than some experimentation.

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.