我正在使用websocket开发一个PHP应用程序,并试图设置一个计时器。当用户到达页面时,会有30秒的等待间隔,屏幕上会显示一个javascript计时器。我宁愿让服务器在倒计时结束后发送信号,而不是依赖javascript在倒计时完成后发送信号(更不用说用户篡改时间(。
当fork中的进程正在进行时(在本例中为睡眠函数(,用户可以通过websocket发送和接收消息。然而,当fork中的进程完成时,如果用户试图执行更多通过websocket交互的操作,他们就会断开连接,我不知道为什么。
它就像一样简单
//the user will be disconnected if they try to perform any actions after the sleep is finished
if(pcntl_fork()){
sleep(30);
$this->broadcast_message('done');
}
debug('after fork'); //this is displayed twice. Once as soon as it runs, and a second time when the sleep is done
当我使用pcntl_fork时,只有才会发生websocket断开连接。用户没有立即断开连接。如果用户尝试执行其他使用websocket连接的操作,则会断开连接。
我知道是pnctl_fork导致了这个问题,因为我可以在不使用fork的情况下睡眠,然后进行广播,用户不会断开连接,但它会占用其他所有内容,用户在睡眠结束之前无法再与页面交互。
//this works fine. However, this holds everything up and nothing further can be done so it's useless
sleep(30);
$this->broadcast_message('done');
pcntl_fork为子级返回0
,为父级返回PID。因此,在我看来,您可以更改最初的if
检查,以确保在子if(pcntl_fork() === 0){
上进行检查,然后在检查完成后调用子exit
。然后,父进程将永远不会休眠或退出,但30秒后仍会发送一条消息。
修改您的初始代码块:
if(pcntl_fork() === 0){
sleep(30); // Child sleeping
$this->broadcast_message('done');
exit(0); // Child exits
}
// Only the parent gets here, and does so immediately
debug('after fork');
**我意识到这个问题已经很老了,如果不了解更多关于websocket的信息,我不能保证这个问题会起作用,尤其是因为文件句柄和数据库之类的东西在分叉过程中会复制到子对象,所以在子对象中关闭会在父对象中关闭。但我偶然发现了这一点,并想给我2美分,因为在父进程中等待并让子进程继续以未定义的方式运行代码似乎很奇怪。
我解决了这个问题。对于任何有同样问题的人来说,孩子的过程并没有恰当地结束。
$pid = pcntl_fork();
if($pid){
sleep(30);
$this->broadcast_message('done');
posix_kill($pid, SIGKILL);
}