php进程间通信--消息队列
前面介绍了怎么通过消息管道(有名消息管道)进行进程间通信,下面介绍如何通过消息队列实现进程间通信。
首先我们来看一下如何创建一个消息队列。
1 <?php 2 //创建消息队列 3 $msg_key = ftok( __FILE__, 'a' ); 4 $msg_queue = msg_get_queue( $msg_key, 0666 );
在php中通过这两句话就可以创建一个消息队列。 ftok 函数,是可以将一个路径转换成 消息队列 可用的key值。 msg_get_queue函数的第一个参数 是消息队列的key,第二个参数是消息队列的读写权限,这个权限跟文件类似。这个很重要,设置
不好可能导致你的消息队列不可读写。
消息队列有了,下面看一下如何读写消息队列。
1 <?php 2 //获取消息队列的状态 3 $message_queue_status = msg_stat_queue($msg_queue); 4 5 //向消息队列中写 6 msg_send($msg_queue, 1, "Hello,World!"); 7 8 //从消息队列中 9 msg_receive($msg_queue, 0, $message_type, 1024, $message, TRUE, MSG_IPC_NOWAIT); 10 echo $message . PHP_EOL;
msg_stat_queue 这个函数是查看当前的消息队列的状态,里面包含一些当前消息队列内消息的条数以及其他信息等,有兴趣的可以打印看看。
msg_send函数,向指定消息队列写入信息。原型为 bool msg_send ( resource $queue
, int $msgtype
, mixed $message
[, bool $serialize
= true [, bool $blocking
= true [, int &$errorcode
]]] ), 参数比较多
第1个参数 : resource $queue 表示要写入的消息队列资源。
第2个参数 : int
$msgtype 表示写入消息队列的 消息类型,这个参数是 配合 msg_receive读取消息队列函数 使用的,下面会说。
第3个参数 : mixed $message 你要发送的信息,最大为 65536 个字节。
第4个参数 : bool $serialize
= true 为可选项,是否序列化你发送的消息。
第5个参数 : bool $blocking
= true 是否阻塞,当你发送的消息很大,而此时的消息队列无法存入的时候,此时消息队列就会阻塞,除非等到有别的进程从消息队列中读取了别的消息,然后消息队列有足够的空间存储你要发送的信息,才能继续执行。你可以设置这个参数为false,
这样你发送信息就会失败,此时错误信息会在 第6个参数 $errorcode中体现,错误码为 MSG_EAGAIN ,你可以根据这个错误码,重新发送你的消息。
第6个参数 :
int
&$errorcode 记录写入中出现的一系列错误。
下面我们来看一下 读取函数 msg_receive 。原型为:bool msg_receive ( resource $queue
, int $desiredmsgtype
, int &$msgtype
, int $maxsize
, mixed &$message
[, bool $unserialize
= true [, int $flags
= 0 [, int &$errorcode
]]] )
第1个参数:resource $queue 表示要读取的消息队列资源。
第2个参数 :int $desiredmsgtype 读取的消息类型。这个参数为 0 的时候,你可以读取 msg_send 以任意 消息类型 发送的消息。 如果此参数和你发送的某个消息类型相同,比如你有 2个消息,一个是通过 1类型发送的,一个是通过2 类型发送的。你用 0 可以接收这两种消息
而你用 1 只能接收到 以1类型发送的消息。
第3个参数 : int &$msgtype 你读取到的信息,它发送时的消息类型会存储在该参数中。
第4个参数 : int $maxsize 你以多大的字节去读取消息,如果这个值小于你要读取的内容的长度,你会读取失败。
第5个参数 :mixed &$message 读取的内容。
第6个参数 : bool $unserialize
= true 内容是否序列化
第7个参数 :int $flags
= 0 读取标识。除了默认的0 之外,还有3个参数可选 MSG_IPC_NOWAIT
这个参数表示如果没有从消息队列中读取到信息,会立马返回,并返回错误码
MSG_ENOMSG
.
MSG_EXCEPT
这个参数 是配合 第2个参数使用的,如果使用这个参数,你读取到的第一个参数,不是你第一个发送的参数。(队列先进先出)
MSG_NOERROR
如果读取的内容过大,而你指定的第4个参数又不够的时候,它会截断这个消息,并且不报错。
销毁消息队列的方法 : msg_remove_queue($msg_queue);
好了方法介绍完毕了,来看一下,怎么在父子进程之间实现通信吧。
1 <?php 2 /** 3 * author: NickBai 4 * createTime: 2016/12/3 0003 上午 9:08 5 */ 6 //父子进程通过消息队列通信 7 8 //创建消息队列 9 $msg_key = ftok( __FILE__, 'a' ); 10 $msg_queue = msg_get_queue( $msg_key, 0666 ); 11 12 //启动进程 13 $pid = pcntl_fork(); 14 15 if( $pid == 0 ){ 16 //子进程向父进程报告 17 msg_send( $msg_queue, 1, "father i am " . getmypid(). " and i am working! \n" ); 18 exit(); //退出子进程 19 }else if( $pid ){ 20 21 msg_receive( $msg_queue, 0, $message_type, 1024, $message, TRUE, MSG_IPC_NOWAIT ); 22 echo $message; 23 pcntl_wait( $status ); //阻塞回收子进程 24 if( $status ){ 25 msg_remove_queue( $msg_queue ); 26 } 27 28 }