gpt4 book ai didi

php - PHP socket_accept在非阻塞模式下引发警告

转载 作者:行者123 更新时间:2023-12-03 12:05:28 30 4
gpt4 key购买 nike

我想创建一个简单的PHP服务器(基于TCP),该服务器可以提供实际时间并立即关闭连接。我已经做到了。我想添加crtl-C处理,所以我需要用非阻塞替换阻塞的socket_accept(这是因为当到达阻塞的socket_accept指令并且我发送SIGINT/ctrl-C/时,服务器将仍然处于 Activity 状态,直到第一个客户端是服务器,然后它自身关闭-我不希望出现这种情况)。

我当前的代码如下所示:

<?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)只会抑制警告被抛出,但是仍然不能说明为什么会被抛出...

最佳答案

我在寻找完全相同的问题的解决方案时找到了您的问题。此外,我发现了其他一些帖子问同样的事情,但也没有解决方案。一些帖子指出,没有办法阻止socket_accept()发出警告,因为它是设计用来指示“没有等待的连接来接受”。我无法确认这一点,因为在 socket_accept() 的PHP手册页中似乎没有提到

像您一样,我对使用任何形式的错误抑制都不满意。似乎下一步的逻辑步骤是将socket_accept()包装在某种条件中,以便仅在我知道有连接等待时才执行。我找不到任何能做到这一点的东西。但是,当使用stream_*()函数而不是socket_*()函数时,看起来就像是。因此,我转而使用流(似乎也有其他优点),如下所示:

if (( $socket = stream_socket_server( "tcp://$address:$port", $errno, $errstr )) === FALSE ) {
die( "failed to create socket: $errstr\n" );
}

echo "Waiting for clients to connect...\n";

while ( $server_listening ) {
$read = array( $socket );
$array = array();

if ( stream_select( $read, $array, $array, 0 )) {
$connection = stream_socket_accept( $socket, 0 );

client_handler( $socket, $connection );
} else {
usleep( 100 );
}
}

这似乎运作良好。我的脚本仅在首先确定存在连接等待时才尝试接受该连接。完成此操作后,我确实发现有一个等效的套接字函数 socket_select() 似乎以相同的方式工作。因此,如果您想坚持使用 socket_*()函数,则可以执行类似的操作。

顺便说一句,我很高兴我切换到流,因为它们似乎更易于使用。而且由于我的应用程序仅限于TCP,所以我似乎并没有缺少使用更多低级套接字所能提供的任何功能。

关于php - PHP socket_accept在非阻塞模式下引发警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19339073/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com