PHP套接字服务器占用大量CPU

时间:2015-11-19 14:44:00

标签: php sockets

我在互联网上关注一些教程(1)(2)来创建一个PHP套接字服务器,它运行良好。我的PHP脚本只占用了大量的CPU(99%)。

我这里没有显示代码,因为我的代码与上面的教程类似。

主要动作是用不定式循环写的

while (true)
{
   $this->selectChangedSockets();
   $this->handleNewClients();
   $this->receiveInput();
   $this->checkDisconnections();
}

我的循环中的函数只是处理输入(新客户端的连接,客户端的消息等),并处理输出(发送回客户端的消息等) 。)

我的php脚本始终处于CPU使用率的最高位置(99%)。我读了this,他们建议把'睡觉(1)"在循环。我的套接字服务器是用于实时应用程序的,我不确定这是一个好方法吗?

任何有php socket经验的人都可以给我任何建议吗?

有没有标准的php套接字服务器库? 或者我是否需要在后台运行脚本?

更新

因为你提到函数socket_select可能暂停一点,我给你我的代码:


    private function selectChangedSockets()
    {
        // Reset array of changed sockets
        $this->changed = array_merge(array($this->socket), $this->clients);

        $null = null;
        $res = socket_select($this->changed, $null, $null, 0);
        if (false === $res)
        {
            echo "socket_select() failed, reason: " .
                socket_strerror(socket_last_error()) . "\n";
        }
    }

    public function run()
    {
        while (true) {

            $this->selectChangedSockets();
            //$this->handleNewClients();
            //$this->receiveInput();
            //$this->checkDisconnections();
        }
    }

我的PHP脚本仍然需要99%的CPU使用率。

2 个答案:

答案 0 :(得分:5)

你的selectChangedSockets方法应该是阻塞的,这意味着,在套接字发生变化之前不会返回。请参阅socket_select

while ( true ) {}将使用100%的CPU时间。你需要某种延迟。 由于您可以使用socket_select,因此您可以使用0%的CPU时间指定超时,直到实际完成一些工作为止:

function selectChangedSockets() {
    $read   = array($socket1, $socket2);   // array of your sockets
    $write  = NULL;
    $except = NULL;
    $num_changed_sockets = socket_select($read, $write, $except, NULL);
}

这将等到$read中的一个套接字有可用数据。对于服务器套接字,当客户端建立新连接时会发生这种情况。对于连接的套接字,当客户端发送数据时会发生这种情况。

再次,请参阅socket_select了解详细信息和示例。特别是第一个用户贡献的注释,它使用while (true),处理新连接,并从客户端读取数据。

但请注意,在socket_select页面中,有关第4个参数:

  

tv_sec可能为零,导致socket_select()立即返回。这对轮询非常有用。如果tv_sec为NULL(无超时),则socket_select()可以无限期地阻塞。

答案 1 :(得分:0)

我的解决方法是:

如果套接字服务器空闲5秒(不接收数据),空闲模式,放松CPU,

<?php

if (!($sock = socket_create(AF_INET, SOCK_DGRAM, 0))) {
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);
    die("Couldn't create socket: [$errorcode] $errormsg \n");
}

$server_idle=time();
while (1) {

    $buf="";
    $r = socket_recvfrom($sock, $buf, 512, MSG_DONTWAIT, $remote_ip, $remote_port);
    if ($buf) {
        $server_idle=time();

    //socket process codes
    //.
    //.

    }



    if (time()-$server_idle>5) {  // if Server idle 5 second; IDLE Mode!
        usleep(100);  // IDLE Mode
    } else {
        // usleep(1); // No IDLE Mode usleep(1) milisecond less CPU process
    }

}

?>