PHP Ev 事件扩展如何监听嵌套的事件??

发布于 2022-09-06 21:31:46 字数 1978 浏览 45 评论 0

Linux 使用 PHP Ev 扩展,监听 socket

这边有两个递进的监听:

  1. 监听客户端连接
  2. 客户端连接后,监听客户端进行收发数据

具体实现代码如下:

<?php


$tcp    = "127.0.0.1:9005";
$count  = 2;
$pids   = [];

// 端口多进程监听
for ($i = 0; $i < $count; ++$i)
{
    $pid = pcntl_fork();

    if ($pid < 0) {
        exit('生成子进程失败\n');
    } else if ($pid > 0) {
        // 父进程
        $pids[] = $pid;
    } else {
        var_dump("产生子进程 {$i}");

        // 创建资源流上下文
        $context = stream_context_create([
            'socket' => [
                //
                'backlog' => 102400
            ]
        ]);

        // 设置端口重用
        stream_context_set_option($context , 'socket' , 'so_reuseport' , 1);

        // 监听客户端链接 + 设置端口重用
        $server = stream_socket_server($tcp , $errno , $errstr , STREAM_SERVER_BIND | STREAM_SERVER_LISTEN , $context);
        $clients = [];

        // 如果资源可读,读取,并且一直监听
        $ev = new EvIo($server , Ev::READ , function($watcher) use($clients , $server){

            var_dump("接收到客户端链接");
            var_dump($watcher->fd === $server);

            // $client     = stream_socket_accept($watcher->fd);
            $client     = stream_socket_accept($server);
            $clients[]  = $client;

            // 设置资源阻塞模式
            stream_set_blocking($client , false);

            // 事件监听
            $ev = new EvIO($client , Ev::READ | Ev::WRITE , function($watcher) use($client , $clients){
                var_dump($watcher->fd === $client);

                var_dump("客户端资源可读!!");
            });

            var_dump("监听客户端数据收发已经就绪");
        });

        // 开始事件监听!
        Ev::run();

        // 不要进入父进程领域
        exit;
    }
}

foreach ($pids as $v)
{
    pcntl_waitpid($v , $status , WUNTRACED);
}

var_dump("所有进程都已经退出");

运行后发现,如果有客户端连接,则触发回调函数,但是,如果该客户端发送了数据到服务器,却没有触发回调。

不知道该如何破解??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

—━☆沉默づ 2022-09-13 21:31:46

EvIo 有些特性:

  • 同作用域下,同类事件会相互覆盖,后面定义的覆盖前面的
  • 嵌套事件,需要再次执行 Ev::run 才会触发,再次调用 Ev::run 后事件的执行不可预测。

基于上面两个,我发现了一个特殊的现象:

function login($fd , $flag , $callback , $args){
    return new EvIo($fd , $flag , $callback , $args);
}

// 这种方式定义多个重复事件,都会触发 ..
// 无语,但是目前就是用这种方式投入使用的
$one = login($socket , Ev::READ , null , null);
$two = login($socket , Ev::READ , null , null);

// 跑进程
Ev::run();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文