How to open a socket connection?

0

I have an application in PHP / Javascript (using the jQuery framework), I want to open a connection via socket to a chat system, similar to Google's G-talk, but I can not open socket at all.

I can not use any solution based on node.js .

I've tried the following:

CLIENT

<!DOCTYPE HTML>
<html>
    <head>
        <script type="text/javascript">
            WebSocketTest()
            function WebSocketTest(){   
                // Let us open a web socket
                var ws = new WebSocket("ws://localhost/index.php");

                ws.onopen = function(){
                    // Web Socket is connected, send data using send()
                    ws.send("Message to send");
                    alert("Message is sent...");
                };

                ws.onmessage = function (evt)   { 
                    var received_msg = evt.data;
                    alert("Message is received...");
                };

                ws.onclose = function(){ 
                    // websocket is closed.
                    alert("Connection is closed..."); 
                };
            }
        </script>
    </head>
    <body>
        [...]
    </body>
</html>

SERVER

<?php
    error_reporting(E_ALL);

    echo "<h2>TCP/IP Connection</h2>\n";

    /* Get the port for the WWW service. */
    $service_port = getservbyname('www', 'tcp');

    /* Get the IP address for the target host. */
    $address = gethostbyname('localhost');

    /* Create a TCP/IP socket. */
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    if ($socket === false) {
        echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
    } else {
        echo "OK.\n";
    }

    echo "Attempting to connect to '$address' on port '$service_port'...";
    $result = socket_connect($socket, $address, $service_port);
    if ($result === false) {
        echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";
    } else {
        echo "OK.\n";
    }

    $in = "HEAD / HTTP/1.1\r\n";
    $in .= "Host: localhost\r\n";
    $in .= "Connection: Close\r\n\r\n";
    $out = '';

    echo "Sending HTTP HEAD request...";
    socket_write($socket, $in, strlen($in));
    echo "OK.\n";

    echo "Reading response:\n\n";
    while ($out = socket_read($socket, 2048)) {
        echo $out;
    }

    echo "Closing socket...";
    socket_close($socket);
    echo "OK.\n\n";
?>

However, I get the following error:

  

ebSocket connection to 'ws: //localhost/chat_4/index.php' failed: Error during WebSocket handshake: Unexpected response code: 200

Would you have a more practical solution to check when a message was dynamically inserted into the database?

    
asked by anonymous 01.02.2016 / 22:31

1 answer

3

Good morning, I do not know if you already got your solution, but I can help with a solution that works on some of my systems.

Server Side server.php

<?php
$host = '127.0.0.1';
$port = '9000';
$null = NULL;

above you define your host, connection port, and variable with null value. Note: It is important to define the host with the address of your server (IP).

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($socket, 0, $port);
socket_listen($socket);
$clients = array($socket);


while (true) {
    $changed = $clients;
    socket_select($changed, $null, $null, 0, 10);

if (in_array($socket, $changed)) {
    $socket_new = socket_accept($socket);
    $clients[] = $socket_new;

    $header = socket_read($socket_new, 1024);
    perform_handshaking($header, $socket_new, $host, $port);

    socket_getpeername($socket_new, $ip);
    $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected')));
    send_message($response);

    $found_socket = array_search($socket, $changed);
    unset($changed[$found_socket]);
}

At this point 'below' I start creating an array that will be converted to json. This data will be the ones that will be launched in the socket tunnel, that is, the communication between your server and client will be done by this json.

Obs. these values can be defined according to your need and utility.

foreach ($changed as $changed_socket) { 


    while(socket_recv($changed_socket, $buf, 1024, 0) >= 1)
    {
        $received_text = unmask($buf); //unmask data
        $tst_msg = json_decode($received_text);

        $user_id_cliente = $tst_msg->id_cliente;
        $empresa_id = $tst_msg->empresa_id;
        $user_time_mensagem = $tst_msg->time_mensagem;
        $user_conteudo_mensagem = $tst_msg->conteudo_mensagem;
        $user_nome_cliente = $tst_msg->nome_cliente;
        $quem_esta_enviado = $tst_msg->quem_envia;
        $produto_detalhes = $tst_msg->produto_detalhes;
        $grupo_men = $tst_msg->grupo_mensagem;
        $nome_empresa = $tst_msg->nome_empresa;

        $regra_empresa = $tst_msg->regra_empresa;
        $atacado_empresa = $tst_msg->atacado_empresa;
        $min_empresa = $tst_msg->min_empresa;
        $cidade_cliente = $tst_msg->cidade_cliente;
        $valor_pedido = $tst_msg->valor_pedido;
        $pedido_mandar = $tst_msg->pedido_mandar;

        $response_text = mask(json_encode(array('nome_empresa'=>$nome_empresa,'grupo_mensagem'=>$grupo_men,'pedido_mandar'=>$pedido_mandar,'regra_empresa'=>$regra_empresa,'atacado_empresa'=>$atacado_empresa,'min_empresa'=>$min_empresa,'cidade_cliente'=>$cidade_cliente,'valor_pedido'=>$valor_pedido,'produto_detalhes'=>$produto_detalhes,'quem_envia'=>$quem_esta_enviado,'empresa_id'=>$empresa_id,'id_cliente'=>$user_id_cliente, 'time_mensagem'=>$user_time_mensagem, 'conteudo_mensagem'=>$user_conteudo_mensagem, 'nome_cliente'=>$user_nome_cliente)));
        send_message($response_text); //send data
        break 2; //exist this loop
    }

continuing ...

    $buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ);
    if ($buf === false) { 
        $found_socket = array_search($changed_socket, $clients);
        socket_getpeername($changed_socket, $ip);
        unset($clients[$found_socket]);

        $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected')));
        send_message($response);
    }
}
}

socket_close($socket);

function send_message($msg)
{
    global $clients;
    foreach($clients as $changed_socket)
    {
        @socket_write($changed_socket,$msg,strlen($msg));
    }
    return true;
}


function unmask($text) {
    $length = ord($text[1]) & 127;
    if($length == 126) {
        $masks = substr($text, 4, 4);
        $data = substr($text, 8);
    }
    elseif($length == 127) {
        $masks = substr($text, 10, 4);
        $data = substr($text, 14);
    }
    else {
        $masks = substr($text, 2, 4);
        $data = substr($text, 6);
    }
    $text = "";
    for ($i = 0; $i < strlen($data); ++$i) {
        $text .= $data[$i] ^ $masks[$i%4];
    }
    return $text;
}

function mask($text)
{
    $b1 = 0x80 | (0x1 & 0x0f);
    $length = strlen($text);

    if($length <= 125)
        $header = pack('CC', $b1, $length);
    elseif($length > 125 && $length < 65536)
        $header = pack('CCn', $b1, 126, $length);
    elseif($length >= 65536)
        $header = pack('CCNN', $b1, 127, $length);
    return $header.$text;
}

function perform_handshaking($receved_header,$client_conn, $host, $port)
{
    $headers = array();
    $lines = preg_split("/\r\n/", $receved_header);
    foreach($lines as $line)
    {
        $line = chop($line);
        if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
        {
            $headers[$matches[1]] = $matches[2];
        }
    }

    $secKey = $headers['Sec-WebSocket-Key'];
    $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));

    $upgrade  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
    "Upgrade: websocket\r\n" .
    "Connection: Upgrade\r\n" .
    "WebSocket-Origin: $host\r\n" .
    "WebSocket-Location: ws://$host:$port/demo/shout.php\r\n".
    "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
    socket_write($client_conn,$upgrade,strlen($upgrade));
}

Client side your-file.js

Remember the host and port? are inserted below

var wsUrir = "ws://127.0.0.1:9000";
    connection = new WebSocket(wsUrir);

open connection, activate the block below

    connection.onopen = function(ev) { 
        console.log('socket aberto');
    };

Transactions, messages, requisitions, etc., run below.

    connection.onmessage = function(ev) {
        var msg_ws = JSON.parse(ev.data);

        var type_ws = msg_ws.type;
        var ws_id_cliente = msg_ws.id_cliente;

        console.log(ev.data);

        if(type_ws !== 'system'){

            // suas condições aqui

        }


    };

If an error occurs during or after the connection, the function below is triggered.

    connection.onerror  = function(ev){
        console.log("Error Occurred - "+ev.data);
    }; 

If the connection closes, below it is triggered

    connection.onclose  = function(ev){
        console.log("conexao fechada"); 
    };

After configuring your files you will have to access your terminal, navigate to the directory that contains the server.php file and type the command:

php -q **server.php**

Obs. make sure you have php installed and that the php variable is global in your OS.

Another important point is that the socket server only works in php with this command line call, that is, if you try to access by direct url in the browser, the file will not execute and if it closes the connection will also be closed. p>

Anyway, if you have any questions contact me, what I know I share. Hugs!

    
16.01.2017 / 13:56