PHP:pcntl_alarm() 和 socket_select() 可以和平存在于同一个线程中吗?

标签 php linux sockets pcntl php-socket

我有一个主要编写的 PHP CLI 脚本,用作聊天客户端连接的聊天服务器(不要问我为什么用 PHP 来做,那是另一个故事哈哈)。

我的脚本利用 socket_select() 函数挂起执行,直到套接字上发生某些事情,此时它醒来,处理事件,并等待下一个事件。现在,我需要每 30 秒左右执行一些例行任务(检查临时禁止的用户是否应该取消禁止、保存用户数据库,以及其他各种各样的事情)。

据我所知,PHP 根本没有很好的多线程支持。我的第一个想法是每次套接字生成事件并让程序再次运行时比较时间戳,但这是非常不一致的,因为服务器很可能闲置数小时并且没有执行我的任何清理例程。

我遇到了 PHP pcntl 扩展,它让我可以使用分配时间间隔来发送 SIGALRM,并且每次发送时都会执行一个函数。这似乎是我的问题的理想解决方案,但是 pcntl_alarm() 和 socket_select() 相互冲突非常糟糕。每次触发 SIGALRM 时,我的套接字控制代码都会发生各种疯狂的事情。

我的程序相当冗长,所以我不能把它全部贴在这里,但这应该无关紧要,因为我不相信我在代码方面做错了什么。我的问题是:有没有办法让 SIGALRM 与等待的 socket_select() 在同一个线程中处理?如果是这样,如何?如果不是,我的替代方案是什么?

这是我的程序的一些输出。我的报警功能只是输出“滴答!”每当它被调用时,就可以很容易地判断什么时候发生了。这是允许它滴答 4 次后的输出(包括错误)(尽管它说了什么,但没有实际尝试连接到服务器):

[05-28-10 @ 20:01:05] Chat server started on 192.168.1.28 port 4050

[05-28-10 @ 20:01:05] Loaded 2 users from file

PHP Notice: Undefined offset: 0 in /home/danny/projects/PHPChatServ/ChatServ.php on line 112

PHP Warning: socket_select(): unable to select [4]: Interrupted system call in /home/danny/projects/PHPChatServ/ChatServ.php on line 116

[05-28-10 @ 20:01:15] Tick!

PHP Warning: socket_accept(): unable to accept incoming connection [4]: Interrupted system call in /home/danny/projects/PHPChatServ/ChatServ.php on line 126

[05-28-10 @ 20:01:25] Tick! PHP Warning: socket_getpeername() expects parameter 1 to be resource, boolean given in /home/danny/projects/PHPChatServ/ChatServ.php on line 129

[05-28-10 @ 20:01:25] Accepting socket connection from PHP Notice: Undefined offset: 1 in /home/danny/projects/PHPChatServ/ChatServ.php on line 112

PHP Warning: socket_select(): unable to select [4]: Interrupted system call in /home/danny/projects/PHPChatServ/ChatServ.php on line 116

[05-28-10 @ 20:01:35] Tick!

PHP Warning: socket_accept(): unable to accept incoming connection [4]: Interrupted system call in /home/danny/projects/PHPChatServ/ChatServ.php on line 126

[05-28-10 @ 20:01:45] Tick!

PHP Warning: socket_getpeername() expects parameter 1 to be resource, boolean given in /home/danny/projects/PHPChatServ/ChatServ.php on line 129

[05-28-10 @ 20:01:45] Accepting socket connection from

PHP Notice: Undefined offset: 2 in /home/danny/projects/PHPChatServ/ChatServ.php on line 112

最佳答案

pcntl_alarmsocket_select 可以共存,但您需要知道如何正确地做到这一点。

特别是,如果在 socket_select() 等待时警报响起,则在处理警报后,socket_select() 将立即返回并显示错误指示。错误是“中断的系统调用”,这就是您在输出中看到的内容。您需要专门检查该错误,然后重试 socket_select()

或者,您可以忘记使用警报,而是使用 socket_select() 的超时功能。这就是 tv_sec 参数的用途 - 它以秒为单位给出超时,之后即使没有套接字准备好,socket_select() 也会返回。然后您可以进行常规处理。

关于PHP:pcntl_alarm() 和 socket_select() 可以和平存在于同一个线程中吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2933343/

相关文章:

php - 在 PHP 中,什么时候应该使用静态方法与抽象类?

php - 使用用户名和/或电子邮件登录

c++ - 凯特安装问题

c# - 无法访问 System.Net.Sockets.TcpClient 中已处置的对象

php - 根据PHP中的值对数组进行排序

php - 列出数据库中的所有表

linux - 当数据到达 Linux 中的串行端口(RS232)时,是否可以向用户应用程序发送通知消息?

linux - 在用户模式下获取进程的时间片

ios - 客户端和服务器上都无法使用 socket.io 连接到服务器

c++ - 将数组传递给发送UDP数据包的函数