php stream_socket_pair 乱入如何解决??
本来使用 stream_socket_pair
是用来父子进程间通信的,实现多进程下,某个子进程消息通过父进程转发给其他子进程(类似于 qq
),但是这碰到了一个问题:
$count = 4;
$childConn = [];
$parent = null;
for ($i = 0; $i < $count; ++$i)
{
$pair = stream_socket_pair(STREAM_PF_UNIX , STREAM_SOCK_STREAM , STREAM_IPRROTO_IP);
$pid = pcntl_fork();
if ($pid < 0) {
throw new Exception("创建子进程失败");
} else if ($pid > 0) {
fclose($pair[1]);
$child = $pair[0];
$childConn[$pid] = $child;
// 监听子进程消息
listenChild($child);
} else {
fclose($pair[0]);
$parent = $pair[1];
// 监听父进程消息
listenParent($parent);
}
}
以上目的就是为每个子进程创建与父进程的通信通道,然结果却发生了令人意外的效果!
比如下面一个通信过程:
父进程pid: 30246
子进程pid: 30247 30248 30249 30250,每个子进程中都监听客户端连接。
1. 客户端A 进入子进程 30247
2. 客户端B 进入子进程 30248
3. A 客户端发送消息,子进程 30247 接受到消息,要求转发给 30248 中的客户端 B
4. 子进程 30247 调用事先保存的 $parent(与父进程的通信连接),发送消息
... 意外产生了!!
你可能想当然的以为,他绝对是发送给父进程(30246)!
而实际上不是!结果可能是其他子进程!
到这儿,我就很郁闷了,stream_socket_pair 创建的成对套接字,怎么会发生这种现象??
我表示特别无语了 ....跪求大神解救
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
坑人代码还原如下
产生的进程信息:
坑人的结果:
父进程代码领域下(子进程乱入到父进程领域!)
子进程代码领域(正确)
分析:为什么子进程会调用在父进程定义的事件呢??
这得仔细分析
for
循环!Event::$events
添加子进程监听事件,子进程平行执行。对产生的第一个子进程来说,Event::$events
为空,所以没有拷贝到父进程的事件。Event::$events
再次添加监听子进程事件,此时,对产生的第二个子进程来说,Event::$events
存在一个事件!从父进程拷贝了一个事件。Event::$events
再次添加监听子进程事件,此时,对产生的三个子进程来说,Event::$events
存在两个事件!从父进程拷贝了两个事件。Event::$evnets
添加事件,此时,相对产生的第四个子进程来说,Event::$events
存在三个事件,从父进程拷贝了三个事件。由上可知,子进程实际也在监听从父进程拷贝的事件,如果事件触发,那么监听该事件的父子进程实际上都会触发。从而出现了令人郁闷的:子进程乱入到了父进程的领域。
解决方法
在子进程中,把从父进程拷贝的事件销毁即可。