1. 程式人生 > >php程序間通訊--訊息佇列

php程序間通訊--訊息佇列

首先我們來看一下如何建立一個訊息佇列。

//建立訊息佇列

$msg_key = ftok( __FILE__, 'a' );
$msg_queue = msg_get_queue( $msg_key, 0666 );

 在php中通過這兩句話就可以建立一個訊息佇列。 ftok 函式,是可以將一個路徑轉換成 訊息佇列 可用的key值。 msg_get_queue函式的第一個引數 是訊息佇列的key,第二個引數是訊息佇列的讀寫許可權,這個許可權跟檔案類似。這個很重要,設定

不好可能導致你的訊息佇列不可讀寫。

  訊息佇列有了,下面看一下如何讀寫訊息佇列。

<?php
//獲取訊息佇列的狀態
$message_queue_status = msg_stat_queue($msg_queue);

//向訊息佇列中寫
msg_send($msg_queue, 1, "Hello,World!");

//從訊息佇列中
msg_receive($msg_queue, 0, $message_type, 1024, $message, TRUE, MSG_IPC_NOWAIT);
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); 

  好了方法介紹完畢了,來看一下,怎麼在父子程序之間實現通訊吧。

<?php

//父子程序通過訊息佇列通訊

//建立訊息佇列
$msg_key = ftok( __FILE__, 'a' );
$msg_queue = msg_get_queue( $msg_key, 0666 );

//啟動程序
$pid = pcntl_fork();

if( $pid == 0 ){
    //子程序向父程序報告
    msg_send( $msg_queue, 1, "father i am " . getmypid(). " and i am working! \n" );
    exit();  //退出子程序
}else if( $pid ){

    msg_receive( $msg_queue, 0, $message_type, 1024, $message, TRUE, MSG_IPC_NOWAIT );
    echo $message;
    pcntl_wait( $status );  //阻塞回收子程序
    if( $status ){
      msg_remove_queue( $msg_queue );
    }

}