当前位置: 首页 > 知识库问答 >
问题:

如何在PHP中使用命名管道在不同的函数甚至不同的进程之间没有分叉?

康文昌
2023-03-14

我想写一个Ajax网络应用程序,具体来说是一个游戏。两个Web客户端必须通过PHP服务器相互通信。我解决这个问题的方法是在客户端和服务器以及服务器和客户端之间使用Ajax。每个客户端使用Ajax创建一个单独的服务器进程。我希望这两个服务器进程通过MySQL和命名管道进行通信。我需要命名管道来立即响应整个应用程序。

我不能使用一个服务器进程,它首先创建一个管道,然后分叉成两个进程,这两个进程使用管道。当Web浏览器发送请求时,Web应用程序创建服务器进程。因此,我需要命名管道,其中每个进程只知道命名管道的文件名。他们不能交换文件句柄(至少我不知道如何交换)。

我的问题是,只要在同一个函数中使用,以PHP方式命名的管道确实可以工作:

public function writeAndReadPipe_test(){
    $pipeA = fopen("testpipe",'r+');
    fwrite($pipeA, 'ABCD');

    $pipeB = fopen("testpipe",'r+');
    $content = fread($pipeB, 4);
    echo "[" . $content . "]<br>\n";
}

public function testingPipes_same_function(){
    posix_mkfifo("testpipe", 0777);
    $this->writeAndReadPipe_test();
}

但是,当我使用不同的函数时,fread($pipeB,4)命令会阻塞整个应用程序:

public function writePipe_test(){
    $pipeA = fopen("testpipe",'r+');
    fwrite($pipeA, 'ABCD');
}

public function readPipe_test(){
    $pipeB = fopen("testpipe",'r+');
    $content = fread($pipeB, 4);
    echo "[" . $content . "]<br>\n";
}

public function testingPipes_different_functions(){
    posix_mkfifo("testpipe", 0777);
    $this->writePipe_test();
    $this->readPipe_test();
}

有人知道为什么吗?在第一步,我能做些什么来使它在不同的功能之间工作?在第二步中,它甚至应该在不同的过程之间工作!我发现,当作者在读者阅读之前关闭管道时,我也会遇到一个问题。我假设函数在结束时自动关闭它,但这只是一种猜测。

如果PHP方式不起作用,我计划让PHP打开一个命令行,生成BASH命令并让它们执行。只要我的网络服务器在LAMP环境中工作,这在任何情况下都应该有效。缺点是它不能在WAMP环境中工作。

那么,有人对此有什么想法吗?

我需要阻塞管道,让读者等待事件发送。我知道管道可以在非阻塞模式下使用

stream_set_blocking($pipe,false);

或者是这样,但是整个想法是不使用轮询来完成,只使用管道,一旦事件被触发,管道就会唤醒读取器。

共有3个答案

卫弘图
2023-03-14

我不确定我是否理解你最后的第二篇帖子。。

但是评论一下最后一个,如果我没有误解的话,TCP可能会更复杂,因为你必须在读写之前建立一个连接,所以你有不同的开销

至于功能端的管道手柄关闭,我假设您将面临与套接字相同的问题;但是管道文件仍然存在!

持久存储(文件,数据库)将使客户端在时间上独立,如果你想使用阻塞调用,那么文件实际上可能是一种方法...

寇丰
2023-03-14

当您像这样在单独的函数中使用管道时,写入管道A似乎再次被关闭/丢弃($pipeA的本地范围)。假设管道必须打开以供读取和/或写入,以便保留任何信息,这真的很有意义。虽然我不知道内在的魔力。

您还可以观察到,当您从另一个进程馈送管道时,您的阻塞读取调用成功

如果你改变它如下工作:

    private $pipeA;
    public function writePipe_test(){
        $this->pipeA = fopen("testpipe",'r+');
        fwrite($this->pipeA, 'ABCD');
    }

编辑:或者将$pipeA设置为全局范围。。

松高歌
2023-03-14

只是一个简短的声明,我实际上找到了一个很好的解决方案,使用命名管道:

public function createPipe_test(){
    posix_mkfifo("testpipe", 0777);
}

public function writePipe_test($value){
    $pipeA = fopen("testpipe",'w');
    $valueString = number_format($value);
    $valueLen = number_format(strlen($valueString));
    fwrite($pipeA, $valueLen);
    fwrite($pipeA, $valueString);
}

public function readPipe_test(){
    $pipeB = fopen("testpipe",'r');
    $valueLen = fread($pipeB, 1);
    return fread($pipeB, $valueLen);
}

我有两个过程。

如果进程1调用writepe_test(),则它将等待进程2调用readPipe_test()从管道中读取数据。

如果进程1调用readPipe_test(),则它会等到进程2调用writePipe_test()将某些内容写入管道。

诀窍是“w”和“r”而不是“r”。

 类似资料:
  • 我有一个管道脚本,如下所示: ${build_type}可以是“发布”或“调试”。 当我的构建收到触发器时,我希望我的管道为${build_type}中的每个参数运行一次,然后向我发送一封电子邮件,其中包含有关两个构建的报告。 我怎样才能做到这一点? 我试图在编译阶段内定义一个并行块,并在那里设置build_type,但这并不能使其他阶段并行运行。

  • 问题内容: 有一个令人毛骨悚然的项目,其中包含多个spider。我有什么方法可以定义为哪个spider使用哪个管道?并非我定义的所有管道都适用于每个spider。 问题答案: 在Pablo Hoffman的解决方案的基础上,你可以在对象的方法上使用以下装饰器,以便它检查你的Spider属性是否应执行。例如: 为了使此装饰器正常工作,蜘蛛程序必须具有管道属性,其中包含要用于处理项目的管道对象的容器,

  • 问题内容: 我对sklearn中的管道还很陌生,并且遇到了这个问题:我有一个包含文本和数字混合的数据集,即某些列仅包含文本,其余的列具有整数(或浮点数)。 我想知道是否有可能建立一个管道,例如我可以调用文本功能和数字列。我在网上看到的示例大多指向在整个数据集而不是在选择列上使用。这可能吗?如果是这样,任何指针将不胜感激。 问题答案: 我通常的做法是使用,使用a拉出相关的列。 重要笔记: 您必须使用

  • 我得到了(超过)两个Api POSTendpoint。每一个都需要一个json作为参数。但是当我在两个endpoint参数类中使用相同的类名负载时,Swagger就不起作用了。当我改变其中的一个,例如从有效载荷到有效载荷1时,它就不起作用了。当然,我在包装类中设置了正确的名称空间,以便它找到负载。但我希望每次都使用相同的名称“有效载荷”。如何使用相同的类名负载?在这两种情况下,我都可以保留json

  • 问题内容: 这是一个关于如何将cookie从一个casperjs页持久化到另一个页面的问题。 所以基本上我得到了一个nodejs文件,该文件生成casperjs作为工作人员执行某些任务。一个是登录,一旦登录,我就将cookie存储在文件中。 当我产生下一个Casper工人时..我希望它使用Cookie而不是再次登录..这两种方法均 失败 : 第一: 当我生成worker capserjs时,我添加

  • 我试图使用命名管道在同一台机器上的服务器和客户端进程之间进行通信。服务器向客户机发送一条消息,客户机对其执行操作并返回结果,服务器应该得到结果。 这里是服务器的代码: 以下是客户端的代码: 但是在服务器代码中,在线pipeServer。WaitForPipeDrain();我得到一个ObjectDisposedException,它说“无法访问封闭管道。” 在设置sw时,我在打开的客户端代码中也会