php进程通信-PIPE管道通信

上一篇文章讲到了php进程通信的进程信号通信方法,本文介绍的是有名管道:

管道通信,主要是利用文件,写入以及读取来进行通信的,

通俗来讲,就是A进程在1.txt写入1,B进程读取1.txt,就能读取到这个1,这样就通信成功了.

当然,php进程管道通信没有这么简单

注意:多进程系列文章,都建立在linux环境,php-cli运行模式下

一:创建个专属管道的文件:

 $fifoPath = "tmp/$name".getmypid() ;//定义文件名
        if (!file_exists($fifoPath)) {
            if (!posix_mkfifo($fifoPath, 0666)) {//posix函数,创建一个特殊的pipe文件
//                error("create new pipe ($name) error.");
                return false;
            }
        } else {
//            error("pipe ($name) has exit.");
            return false;
        }

二:读取数据

$r_pipe = fopen($fifoPath, 'r');//正常读取文件
if ($r_pipe == NULL) {
    return false;
}

$data = fread($r_pipe, 1024);

三:写入数据

$w_pipe = fopen($fifoPath, 'w');//正常操作文件一样打开该管道
if ($w_pipe == NULL) {
    throw new Exception('打开管道错误!');
}

$result = fwrite($w_pipe, $data);//写入文件一样写入数据

四:删除管道

unlink($tfifoPath);//删除文件

五:封装类

<?php

/**
 * Created by PhpStorm.
 * User: tioncico
 * Date: 18-5-21
 * Time: 下午11:51
 */
class Pipe
{
    public $fifoPath;
    private $w_pipe;
    private $r_pipe;

    /**
     * 自动创建一个管道
     *
     * @param string $name 管道名字
     * @param int $mode 管道的权限,默认任何用户组可以读写
     */
    function __construct($name = 'pipe', $mode = 0666)
    {
        $fifoPath = "tmp/$name".getmypid() ;
        if (!file_exists($fifoPath)) {
            if (!posix_mkfifo($fifoPath, $mode)) {
//                error("create new pipe ($name) error.");
                return false;
            }
        } else {
//            error("pipe ($name) has exit.");
            return false;
        }
        $this->fifoPath = $fifoPath;
    }

///////////////////////////////////////////////////
//  写管道函数开始
///////////////////////////////////////////////////
    function open_write()
    {
        $this->w_pipe = fopen($this->fifoPath, 'w');
//        var_dump($this->w_pipe);
        if ($this->w_pipe == NULL) {
            throw new Exception('打开管道错误!');
//            return false;
        }
        return true;
    }

    function write($data)
    {
        return fwrite($this->w_pipe, $data);
    }

    function write_all($data)
    {
        $w_pipe = fopen($this->fifoPath, 'w');
        fwrite($w_pipe, $data);
        fclose($w_pipe);
    }

    function close_write()
    {
        return fclose($this->w_pipe);
    }
/////////////////////////////////////////////////////////
/// 读管道相关函数开始
////////////////////////////////////////////////////////
    function open_read()
    {
        $this->r_pipe = fopen($this->fifoPath, 'r');
        if ($this->r_pipe == NULL) {
//            error("open pipe {$this->fifoPath} for read error.");
            return false;
        }
        return true;
    }

    function read($byte = 1024)
    {
        return fread($this->r_pipe, $byte);
    }

    function read_all()
    {
        $r_pipe = fopen($this->fifoPath, 'r');
        $data   = '';
        while (!feof($r_pipe)) {
            //echo "read one K\n";
            $data .= fread($r_pipe, 1024);
        }
        fclose($r_pipe);
        return $data;
    }

    function close_read()
    {
        return fclose($this->r_pipe);
    }
////////////////////////////////////////////////////

    /**
     * 删除管道
     *
     * @return boolean is success
     */
    function rm_pipe()
    {
        return unlink($this->fifoPath);
    }
}

六:注意事项

1:管道与普通文件有一点非常不同的就是:管道需要先有个进程读取进程,才可以写入,否则按写入模式打开文件时阻塞,以下是测试截图:


仙士可博客

仙士可博客



仙士可博客
请先登录后发表评论
  • 最新评论
  • 总共0条评论
  • 本站由白俊遥博客程序搭建
    © 2017-1-17 php20.cn 版权所有 ICP证:闽ICP备17001387号
  • 联系邮箱:1067197739@qq.com