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
&$errorcode
]]] ), 引數比較多
第1個引數 : resource $queue 表示要寫入的訊息佇列資源。
第2個引數 : int
$msgtype 表示寫入訊息佇列的 訊息型別,這個引數是 配合 msg_receive讀取訊息佇列函式 使用的,下面會說。
第3個引數 : mixed $message 你要傳送的資訊,最大為 65536 個位元組。
第4個引數 : bool $serialize
第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 );
}
}