PHP进程通信-消息队列的使用

1.PHP中消息队列的行为表现

1.它不会像管道一样,写操作后会阻塞,直到管道被读取。每一次发送消息到指定的msg_type队列中,不会阻塞,可以一直发。接受消息时,不是每次接受成功都能返回正确的消息,可能是一条空消息。

2.消息队列接收的行为默认是阻塞的,可以通过flag标志调整是否为非阻塞

3. msg_receive 第二个参数 $desiredmsgtype 为0的时候,取得是队列头的消息,>0 取的时msg_type 的消息,<0 取得是 绝对值对应得msg_typed的消息。

4.它不像共享内存或者管道一样,每次写要么覆盖,要么追加。它是独立的存储空间,每次对同一个msg_type发送消息,会产生独立的消息。当消息被读取时,该消息就会从消息队列中移除。

2.代码演示消息队列的操作

<?php

$msg_key = ftok(__FILE__, 'a');

$msg_queue = msg_get_queue($msg_key);

$pid = pcntl_fork();

$childs = [];

for($i = 0; $i < 3; $i++) {
    if ($pid === -1) {
        exit;
    } else if ($pid) {
        $arr = range(3, 100);

        $childs[] = $pid;

        foreach($arr as $k => $val) {
            if (msg_queue_exists($msg_key)) {
                msg_send($msg_queue, 2, $val%2);

                printf("send by pid:%d for num %d" . PHP_EOL, posix_getpid(),$val);

                usleep(1000);
            }
        }

        printf("over by pid:%d" . PHP_EOL, posix_getpid());

        $status = msg_stat_queue($msg_queue);

        while($status['msg_qnum'] > 0) {
        }

        echo $status['msg_qnum'] . PHP_EOL;

        msg_remove_queue($msg_queue);
    } else {
        while(msg_receive($msg_queue, 0, $msg_type, 1024, $message)) {
            printf("receive by pid:%d msg_type:%d" . PHP_EOL, posix_getpid(), $msg_type);

            if (!$message) {
                echo 'no message' . PHP_EOL;
                continue;
            }

            echo $message . 'pid:' . posix_getpid() . PHP_EOL;
        }
        exit;
    }
}


while (count($childs) > 0) {
    foreach ($childs as $key => $pid) {
        $status = pcntl_waitpid($pid, $status);
        if ($status == -1 || $status > 0) {
            unset($childs[$key]);
        }
    }
}

如无特殊说明,文章均为本站原创,转载请注明出处。如发现有什么不对的地方,希望得到您的指点。

发表评论

电子邮件地址不会被公开。 必填项已用*标注