我在互联网上关注一些教程(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使用率。
答案 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
}
}
?>