web-socket php中的问题

Posted

技术标签:

【中文标题】web-socket php中的问题【英文标题】:issue in web-socket php 【发布时间】:2018-06-29 12:57:31 【问题描述】:

我在php 中使用了WebSocket。但不知何故它会在一段时间后关闭(这么多请求)。

不管怎样处理?

我们在停止后尝试运行它时出现以下错误:

socket_bind(): 无法绑定地址 [10013]: 已尝试 以访问权限禁止的方式访问套接字。 在第 52 行的 C:\wamp64\www\Websocket\server.php 中

警告:socket_listen():无法侦听套接字 [10022]:提供的参数无效。 在 C:\wamp64\www\Websocket\server.php 第 55 行

这是我的代码:

<?php
set_time_limit(0);
error_reporting(E_ALL);
//include 'Triangulate.php';

$filename = 'logs.txt';

class Values

    public $distance;
    public $rasp_id;
    public $rssi;


$host = '10.37.54.167'; //host
$port = '9000'; //port
$null = null; //null var


$rasp = array(
    47 => array(17, 0),
    124 => array(1,6.4),
    43 => array(1,0),
    44 => array(4.6,2));

//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);
$distance = array();
$totalbicken = array(array());
//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);
    $fp = fopen($filename, 'a+');
    //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, 1024); //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
        fwrite ($fp,$response . "\n");
      //  send_message($response); //notify all users about new connection
        // send_message_socket($response, $socket_new);
        //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
        try 
            while (socket_recv($changed_socket, $buf, 1024, 0) >= 1) 
                $received_text = unmask($buf); //Unmask Recive data.
                fwrite ($fp,"Text receive:" . $received_text . "\n");
                $tst_msg = json_decode($received_text); //json decode.
                fwrite ($fp,"Json Decord!". "\n");
                if (!isset($tst_msg->action)) 
                 else 
                    $user_action = $tst_msg->action; //sender name.
                    if ($user_action == "distance")  //If action is distance.
                        $rasp_id = $tst_msg->rasp_id; //get raspberry uniq id.
                        $beacon_id = $tst_msg->beacon_id; //get beacon id
                        $distance_temp = $tst_msg->distance; // get distance
                        $rssi = $tst_msg->rssi; //get RSSI.

                    fwrite ($fp,isset($distance[$beacon_id]). "\n");

                       fwrite ($fp,"Get all values!". "\n");
                        // echo mask(json_encode(array('type'=>'message', 'action'=>'distance', 'beacon_id'=>$beacon_id, 'rasp_id'=>$rasp_id, 'distance'=>$distance)));

                        if (isset($distance[$beacon_id])) 
                            $totalbicken[$beacon_id] = count($distance[$beacon_id]); //get total distance of sender beacon
                         else 
                            $totalbicken[$beacon_id] = 0;
                        
                        if (isset($rasp[$rasp_id])) 
                            echo "\nRequest from: " . $rasp_id;
                            $myVal = new Values();
                            $myVal->distance = $distance_temp;
                            $myVal->rasp_id = $rasp_id;
                            $myVal->rssi = $rssi;
                            $flag = false;
                            if (isset($distance[$beacon_id])) 
                                if (count($distance[$beacon_id]) > 0) 
                                    for ($i = 0; $i < count($distance[$beacon_id]); $i++) 
                                        $myTempVal = $distance[$beacon_id][$i];
                                        if (($myTempVal->rasp_id) == $rasp_id) 
                                            $flag = true;
                                            $distance[$beacon_id][$i] = $myVal;
                                            break;
                                        
                                    
                                    if (!$flag) 
                                        $distance[$beacon_id][$totalbicken[$beacon_id]] = $myVal;
                                    
                                 else 
                                    $distance[$beacon_id][$totalbicken[$beacon_id]] = $myVal;
                                
                             else 
                                $distance[$beacon_id][$totalbicken[$beacon_id]] = $myVal;
                            

                            if (count($distance[$beacon_id]) > 2) 
                                /*$data = triangulate($rasp[$distance[$beacon_id][0]->rasp_id], $distance[$beacon_id][0]->distance,
                                $rasp[$distance[$beacon_id][1]->rasp_id], $distance[$beacon_id][1]->distance,
                                $rasp[$distance[$beacon_id][2]->rasp_id], $distance[$beacon_id][2]->distance);*/
                                fwrite ($fp,"Before Triangulation!". "\n");
                                $data = getTrilateration($rasp[$distance[$beacon_id][0]->rasp_id], $distance[$beacon_id][0]->distance,
                                    $rasp[$distance[$beacon_id][1]->rasp_id], $distance[$beacon_id][1]->distance,
                                    $rasp[$distance[$beacon_id][2]->rasp_id], $distance[$beacon_id][2]->distance);
                                fwrite ($fp,"End Triangulation!". "\n");
                                $response_text = mask(json_encode(array('type' => 'message', 'action' => 'distance',
                                'beacon_id' => $beacon_id, 'distance' => $distance[$beacon_id], 'coordinates' => $data)));
                                fwrite ($fp,"Response: ". $response_text . "\n");
                                send_message($response_text);
                            
                        
                    
                    fwrite ($fp,"Break!: ". "\n");
                    break 2; //exist this loop*/
                
            
         catch (Exception $e) 
            fwrite ($fp,"Exception:  done! \n");
            fwrite ($fp,"Exception: ". $e->getMessage(). "\n");
            echo "Exception:" . $e->getMessage();
        

        $buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ);
        if ($buf === false)  // check disconnected client
            // remove client for $clients array
            try 
                $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);
             catch (Exception $e) 
                echo "Exception:" . $e;
            
        
    

// close the listening socket
socket_close($socket);
$fclose ($fp);

function send_message($msg)

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

function send_message_socket($msg, $changed_socket)

    @socket_write($changed_socket, $msg, strlen($msg));
    return true;


//Unmask incoming framed message
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;


//Encode message for transfer to client.
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;

//handshake new client.
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/Websocket/shout.php\r\n" .
        "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
    socket_write($client_conn, $upgrade, strlen($upgrade));

提前致谢!

【问题讨论】:

很高兴看到与错误相关的代码,也许? @AymDev:感谢您的回复。请查看代码的问题。我已经用代码更新了我的问题。 【参考方案1】:

我已经设置了 Linux 环境并进行了测试。它工作正常。这可能是 Windows 中的防火墙问题。

据我所知,较新版本的 windows(在 service pack-3 之后)有一些 RPC 连接规则(HTTP 请求限制和第二次连接),所以这可能是个问题。

请阅读this。

到目前为止,改变操作系统是一种解决方案。

感谢和问候 Jignesh M. Mehta

【讨论】:

以上是关于web-socket php中的问题的主要内容,如果未能解决你的问题,请参考以下文章

web-socket.js 和 WebSocket

web-socket 客户端不会连接到 API

django Web-Sockets 设计和内存数据存储

使用 react 和 express 建立 web-socket 通信(nginx、docker)

推送通知可以代替 web-socket 吗?

Python 在线程类函数中广播更新的 Web-socket 数据