Error with socket

Asked

Viewed 167 times

0

I have a system that uses php web socket for chat communication and real-time notification. It works, but usually gives spikes and the server time in time drops the service.

I’m going to post my code here and ask with all affection if you can help me understand what can be improved, what is wrong, etc.

<?php
$host = '216.172.XXX.XXX';
$port = '2703';
$null = NULL;

$pem_passphrase = '';
$pemfile = 'http://216.172.XXX.XXX/~vendemodac/ssl/certs/vendemoda.pem';
$context = stream_context_create();

stream_context_set_option($context, 'ssl', 'local_cert', $pemfile);

// Pass Phrase (password) of private key
stream_context_set_option($context, 'ssl', 'passphrase', $pem_passphrase);
stream_context_set_option($context, 'ssl', 'allow_self_signed', true);
stream_context_set_option($context, 'ssl', 'verify_peer', false);

// Create the server socket
$socket = stream_socket_server(
    'ssl://'.$host.':'.$port,
    $errno,
    $errstr,
    STREAM_SERVER_BIND|STREAM_SERVER_LISTEN,
    $context
);

//Create TCP/IP sream socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//reuseable port
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);

//bind socket to specified host
socket_bind($socket, 0, $port);

//listen to port
socket_listen($socket);

//create & add listning socket to the list
$clients = array($socket);

//start endless loop, so that our script doesn't stop
while (true) {
    //manage multipal connections
    $changed = $clients;
    //returns the socket resources in $changed array
    socket_select($changed, $null, $null, 0, 10);

    //check for new socket
    if (in_array($socket, $changed)) {
        $socket_new = socket_accept($socket); //accpet new socket
        $clients[] = $socket_new; //add socket to client array

        $header = socket_read($socket_new, 2048); //read data sent by the socket
        perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake

        //socket_getpeername($socket_new, $ip); //get ip address of connected socket
        $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected'))); //prepare json data
        send_message($response); //notify all users about new connection

        //make room for new socket
        $found_socket = array_search($socket, $changed);
        unset($changed[$found_socket]);
    }

    //loop through all connected sockets
    foreach ($changed as $changed_socket) { 

        //check for any incomming data
        while(socket_recv($changed_socket, $buf, 2048, 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;
            $loja_id = $tst_msg->loja_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;

            //prepare data to be sent to client
            $response_text = mask(json_encode(array('nome_empresa'=>$nome_empresa,'grupo_mensagem'=>$grupo_men,'loja_id'=>$loja_id,'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
        }

        $buf = @socket_read($changed_socket, 2048, PHP_NORMAL_READ);
        if ($buf === false) { // check disconnected client
            // remove client for $clients array
            $found_socket = array_search($changed_socket, $clients);
            //socket_getpeername($changed_socket, $ip);
            unset($clients[$found_socket]);

            //notify all users about disconnected connection
            $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')));
    //hand shaking header
    $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));
}

1 answer

1

[I resolved] the question as follows:

I installed and configured the library http://socketo.me

Browser other questions tagged

You are not signed in. Login or sign up in order to post.