【问题标题】:PHP socket server takes a lot of CPU usagePHP 套接字服务器占用大量 CPU 资源
【发布时间】:2016-02-21 18:41:22
【问题描述】:

我按照互联网上的一些教程(1)(2) 创建了一个 PHP 套接字服务器,并且效果很好。唯一的问题是我的 PHP 脚本占用了大量的 CPU 使用率 (99%)。

这里不展示代码,因为我的代码和上面的教程差不多。

主要动作写在不定式循环中

而(真) { $this->selectChangedSockets(); $this->handleNewClients(); $this->receiveInput(); $this->checkDisconnections(); }

my循环中的函数只是处理输入(新客户端的连接、客户端的消息等)和处理输出(发回客户端的消息等)

我的 php 脚本在 CPU 使用率方面始终处于领先地位 (99%)。我读了this,他们建议将“sleep(1)”放在循环中。我的套接字服务器用于实时应用程序,我不确定这是一个好方法吗?

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

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

更新

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

私有函数 selectChangedSockets() { // 重置已更改套接字的数组 $this->changed = array_merge(array($this->socket), $this->clients); $空=空; $res = socket_select($this->changed, $null, $null, 0); 如果(假 === $res) { echo "socket_select() 失败,原因:" 。 socket_strerror(socket_last_error()) 。 "\n"; } } 公共函数运行() { 而(真){ $this->selectChangedSockets(); //$this->handleNewClients(); //$this->receiveInput(); //$this->checkDisconnections(); } }

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

【问题讨论】:

  • 我建议不要使用无限循环,它们会占用大量内存、停止页面加载等,通常是要避免做的事情......
  • 那么,你会建议我做什么?
  • 在 cron 中运行您的代码,尝试查看 this 之类的内容(但没有循环)
  • 所以,每一秒,我都需要重新创建所有东西(socket 连接、mysql 连接、所有变量)?我认为这不是一个好方法。
  • 那为什么不创建一个mysql实例呢?即,$link = mysqli_init(); $link->real_connect("localhost", "dbUsername", "dbPassword", "dbName"); 或者套接字是固定的必需品?

标签: php sockets


【解决方案1】:

您的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() 可以无限期阻塞。

【讨论】:

  • 不,即使我评论了所有这些功能。我的脚本仍然占用 99% 的 CPU 使用率。
  • @chipbk10 好吧,如果您对 socket_select 的调用被阻塞,那么您的 CPU 使用率不应达到 99%,因为该进程应该只是暂停等待通知。您需要添加一个实际显示问题的小示例,而不是对可能具有我们不知道的任何随机实现的方法的调用。
  • 我不相信这是一个答案,您不会尝试回答这个问题,而是向 OP 提出一个问题,请考虑将其删除并添加为评论
  • @SamSwift웃 你说得对,我试图提高效率;-) 不过我确实回答了这个问题——? 之后的所有内容。 ;-)
  • 我的错 - 最后一个(超时)参数必须为 NULL,而不是 0。更新答案。
【解决方案2】:

我的解决办法是:

如果socket server空闲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
    }

}

?>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 1970-01-01
    • 2022-01-01
    • 2011-12-15
    • 1970-01-01
    相关资源
    最近更新 更多