2013-01-25 21 views
2

我使用以下websocket php類作爲我的服務器:PHPWebSocket。它在我所能希望的各種方式下運行良好,但我遇到了一些問題。雖然websocket php服務器中的循環速度

我想更新連接客戶端(他們可以走動)的位置,速度可能每0.3秒。我認爲這將是尋找while循環並在那裏添加心跳事件的簡單問題,但在這裏它變得棘手。

// server state functions 
function wsStartServer($host, $port) { 
    if (isset($this->wsRead[0])) return false; 

    if (!$this->wsRead[0] = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) { 
     return false; 
    } 
    if (!socket_set_option($this->wsRead[0], SOL_SOCKET, SO_REUSEADDR, 1)) { 
     socket_close($this->wsRead[0]); 
     return false; 
    } 
    if (!socket_bind($this->wsRead[0], $host, $port)) { 
     socket_close($this->wsRead[0]); 
     return false; 
    } 
    if (!socket_listen($this->wsRead[0], 10)) { 
     socket_close($this->wsRead[0]); 
     return false; 
    } 

    $this->log("Server starting"); 

    $write = array(); 
    $except = array(); 

    $nextPingCheck = time() + 1; 
    while (isset($this->wsRead[0])) { 

     $changed = $this->wsRead; 
     $result = socket_select($changed, $write, $except, 1); 
        **beat()** 
     if ($result === false) { 
      socket_close($this->wsRead[0]); 
      return false; 
     } 
     elseif ($result > 0) { 
      foreach ($changed as $clientID => $socket) { 
       if ($clientID != 0) { 
        // client socket changed 
        $buffer = ''; 
        $bytes = @socket_recv($socket, $buffer, 4096, 0); 

        if ($bytes === false) { 
         // error on recv, remove client socket (will check to send close frame) 
         $this->wsSendClientClose($clientID, self::WS_STATUS_PROTOCOL_ERROR); 
        } 
        elseif ($bytes > 0) { 
         // process handshake or frame(s) 
         if (!$this->wsProcessClient($clientID, $buffer, $bytes)) { 
          $this->wsSendClientClose($clientID, self::WS_STATUS_PROTOCOL_ERROR); 
         } 
        } 
        else { 
         // 0 bytes received from client, meaning the client closed the TCP connection 
         $this->wsRemoveClient($clientID); 
        } 
       } 
       else { 
        // listen socket changed 
        $client = socket_accept($this->wsRead[0]); 
        if ($client !== false) { 
         // fetch client IP as integer 
         $clientIP = ''; 
         $result = socket_getpeername($client, $clientIP); 
         $clientIP = ip2long($clientIP); 

         if ($result !== false && $this->wsClientCount < self::WS_MAX_CLIENTS && (!isset($this->wsClientIPCount[$clientIP]) || $this->wsClientIPCount[$clientIP] < self::WS_MAX_CLIENTS_PER_IP)) { 
          $this->wsAddClient($client, $clientIP); 
         } 
         else { 
          socket_close($client); 
         } 
        } 
       } 
      } 
     } 

     if (time() >= $nextPingCheck) { 
      $this->wsCheckIdleClients(); 
      $nextPingCheck = time() + 1; 
     } 
    } 

    return true; // returned when wsStopServer() is called 
} 

對我來說,它似乎並沒有任何特定的計時器,說它應該每秒運行一次,但它確實如此。我不是在談論ping檢查,即使在while(isset($ this-> wsRead [0])){)之後直接放置我的心跳呼叫,{它每秒只會觸發一次,並且我完全陷入了困境。

我看錯了地方?是否有什麼關於PHP的websocket實現會減慢while循環?

回答

1

您的socket_select調用中有一秒超時 - 這可能是您的延遲引入的地方。如果您希望該呼叫是非阻塞的,那麼您可以在該超時時間內傳遞一個零。

+0

謝謝,我不能爲我的生活找出1秒延遲來自哪裏。我完全忽略了這個事實,即socket_select引入了它自己的延遲。 – Theik