我想创建一个简单的 PHP 服务器(基于 TCP),它可以提供实际时间并立即关闭连接。我已经这样做了。我想添加 crtl-C 处理,所以我需要用非阻塞替换阻塞 socket_accept (这是因为当到达阻塞 socket_accept 指令并且我发送 SIGINT /ctrl-C/ 然后服务器仍然是活动的,直到第一个客户端是服务器,然后它会自行关闭 - 我不希望这种行为)。
我当前的代码如下所示:
<?php
error_reporting(E_ALL);
ob_implicit_flush();
if ($argc != 2)
die("Wrong params");
$address = 'localhost';
$port = $argv[1];
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false)
die(socket_strerror(socket_last_error()) . "\n");
if (socket_bind($sock, $address, $port) === false)
die(socket_strerror(socket_last_error($sock)) . "\n");
if (socket_listen($sock, 5) === false)
die(socket_strerror(socket_last_error($sock)) . "\n");
socket_set_nonblock($sock);
$remote_host = $remote_port = $msgsock = null;
declare(ticks = 1);
function sig_handler($signo)
{
switch ($signo) {
case SIGTERM:
case SIGINT:
global $sock;
socket_shutdown($sock);
socket_close($sock);
echo "Terminating...\n";
exit;
}
}
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGINT, "sig_handler");
echo "Starting server\n";
while (1) {
do {
$msgsock = socket_accept($sock);
usleep(100000);
} while ($msgsock === false);
socket_getpeername($msgsock, $remote_host, $remote_port);
echo "Connection made from {$remote_host}:{$remote_port}\n";
$msg = date('r', time()) . "\n";
socket_write($msgsock, $msg, strlen($msg));
socket_close($msgsock);
};
socket_close($sock);
一切正常,除了一个细节......我每 0.1 秒(= 100000 微秒)收到以下 PHP 警告:
PHP Warning: socket_accept(): unable to accept incoming connection [11]: Resource temporarily unavailable in /home/tomasz/Development/Python/twisted/time-server.php on line 55
PHP Stack trace:
PHP 1. {main}() /home/tomasz/Development/Python/twisted/time-server.php:0
PHP 2. socket_accept() /home/tomasz/Development/Python/twisted/time-server.php:55
我试图实现的是非阻塞接受:PHP 使用服务器套接字,检查是否有任何连接等待服务。我没有 - 等待 0.1 秒。如果有挂起的连接,则提供它。所有功能都可以,只是我不知道为什么会抛出这个警告——我只是想检查是否有任何连接需要服务。修改error_reporting
为E_ERROR
使警告安静,但我希望有更好的方法来解决这个问题......
编辑:
修改socket_accept($sock)
为@socket_accept($sock)
只会阻止警告被抛出,但这仍然没有说明它被抛出的原因......