It looks like msg_receive() allocates a memory with size $maxsize, and only then tries to receive a message from queue into allocated memory. Because my script dies with $maxsize = 1 Gib, but works with $maxsize = 10 Kib.
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
msg_receive — Recebe uma mensagem de uma fila de mensagens
$queue
,$desired_message_type
,&$received_message_type
,$max_message_size
,&$message
,$unserialize
= true
,$flags
= 0,&$error_code
= null
msg_receive() receberá a primeira mensagem da
fila queue
especificada, do tipo especificado por
desired_message_type
.
queue
A fila de mensagens.
desired_message_type
Se desired_message_type
for 0, a mensagem do início
da fila será retornada. Se desired_message_type
for
maior que 0, a primeira mensagem desse tipo será retornada.
Se desired_message_type
for menor que 0, a primeira
mensagem na fila com um tipo menor ou igual ao
valor absoluto de desired_message_type
será lida.
Se nenhuma mensagem corresponder aos critérios, seu script aguardará até que uma
mensagem adequada chegue à fila. Pode-se impedir que o script bloqueie
especificando MSG_IPC_NOWAIT
no
parâmetro flags
.
received_message_type
O tipo de mensagem recebida será armazenado neste parâmetro.
max_message_size
O tamanho máximo da mensagem a ser aceita é especificado pelo
max_message_size
; se a mensagem na fila for maior
que esse tamanho, a função falhará (a menos que se defina
flags
conforme descrito abaixo).
message
A mensagem recebida será armazenada em message
,
a menos que tenham ocorridos erros no recebimento da mensagem.
unserialize
Se definido como
true
, a mensagem será tratada como se tivesse sido serializada usando o
mesmo mecanismo do módulo de sessão. A mensagem será desserializada
e então retornada ao script. Isso permite que se receba facilmente
arrays ou estruturas de objetos complexas de outros scripts PHP, ou se
estiver sendo usado o serializador WDDX, de qualquer fonte compatível com WDDX.
Se unserialize
for false
, a mensagem será
retornada como uma string binária segura.
flags
O parâmetro opcional flags
permite que sejam passados sinalizadores para a
chamada de sistema msgrcv de baixo nível. O padrão é 0, mas pode-se especificar um
ou mais dos seguintes valores (adicionando-os ou usando OR).
MSG_IPC_NOWAIT |
Se não houver mensagens de
desired_message_type , retorna imediatamente e não
espera. A função falhará e retornará um valor inteiro
correspondente a MSG_ENOMSG .
|
MSG_EXCEPT |
Usar este sinalizador em combinação com um
desired_message_type maior que 0 fará com que a
função receba a primeira mensagem que não seja igual a
desired_message_type . |
MSG_NOERROR |
Se a mensagem for maior que max_message_size ,
definir este sinalizador truncará a mensagem para
max_message_size e não sinalizará um erro.
|
error_code
Se a função falhar, o parâmetro opcional error_code
será definido como o valor da variável "errno" do sistema.
Retorna true
em caso de sucesso ou false
em caso de falha.
Após a conclusão bem-sucedida, a estrutura de dados da fila de mensagens é atualizada
da seguinte forma: msg_lrpid
é definido como o ID do
processo do processo chamador, msg_qnum
é decrementado em 1 e
msg_rtime
é definido como a hora atual.
Versão | Descrição |
---|---|
8.0.0 |
queue espera uma instância de SysvMessageQueue
agora; anteriormente, um resource era esperado.
|
It looks like msg_receive() allocates a memory with size $maxsize, and only then tries to receive a message from queue into allocated memory. Because my script dies with $maxsize = 1 Gib, but works with $maxsize = 10 Kib.
This is meant to be run as your apache user in a terminal, call script in note of msg_send and they will communicate.#! /usr/bin/env php<?php $MSGKEY = 519051; // Message $msg_id = msg_get_queue ($MSGKEY, 0600); while (1) { if (msg_receive ($msg_id, 1, $msg_type, 16384, $msg, true, 0, $msg_error)) { if ($msg == 'Quit') break; echo "$msg\n"; } else { echo "Received $msg_error fetching message\n"; break; } } msg_remove_queue ($msg_id);?>
It seems that a maxsize of 2Mb is some sort of a threshold for php, above that msg_receive() starts to use a lot of CPU (with a sender that is pushing messages non-stop receiving 10000 messages jumps up from 0.01 sec to 1.5 sec on my computer) so try to stay below that thresholod if you can.
<?php error_reporting(E_ALL);/** * Example for sending and receiving Messages via the System V Message Queue * * To try this script run it synchron/asynchron twice times. One time with ?typ=send and one time with ?typ=receive * * @author Thomas Eimers - Mehrkanal GmbH * * This document is distributed in the hope that it will be useful, but without any warranty; * without even the implied warranty of merchantability or fitness for a particular purpose. */header('Content-Type: text/plain; charset=ISO-8859-1');echo "Start...\n";// Create System V Message Queue. Integer value is the number of the Queue$queue = msg_get_queue(100379);// Sendoptions$message='nachricht'; // Transfering Data$serialize_needed=false; // Must the transfer data be serialized ?$block_send=false; // Block if Message could not be send (Queue full...) (true/false)$msgtype_send=1; // Any Integer above 0. It signeds every Message. So you could handle multible message // type in one Queue.// Receiveoptions$msgtype_receive=1; // Whiche type of Message we want to receive ? (Here, the type is the same as the type we send, // but if you set this to 0 you receive the next Message in the Queue with any type.$maxsize=100; // How long is the maximal data you like to receive.$option_receive=MSG_IPC_NOWAIT; // If there are no messages of the wanted type in the Queue continue without wating. // If is set to NULL wait for a Message.// Send or receive 20 Messagesfor ($i=0;$i<20;$i++) { sleep(1); // This one sends if ($_GET['typ']=='send') { if(msg_send($queue,$msgtype_send, $message,$serialize_needed, $block_send,$err)===true) { echo "Message sendet.\n"; } else { var_dump($err); } // This one received } else { $queue_status=msg_stat_queue($queue); echo 'Messages in the queue: '.$queue_status['msg_qnum']."\n"; // WARNUNG: nur weil vor einer Zeile Code noch Nachrichten in der Queue waren, muss das jetzt nciht mehr der Fall sein! if ($queue_status['msg_qnum']>0) { if (msg_receive($queue,$msgtype_receive ,$msgtype_erhalten,$maxsize,$daten,$serialize_needed, $option_receive, $err)===true) { echo "Received data".$daten."\n"; } else { var_dump($err); } } }}?>
Consider this e.g. Linux situation:
<?php
//file send.php
$ip = msg_get_queue(12340);
msg_send($ip,8,"abcd",false,false,$err);
//-----------------------------------------------------
<?php
//file receive.php
$ip = msg_get_queue(12340);
msg_receive($ip,0,$msgtype,4,$data,false,null,$err);
echo "msgtype {$msgtype} data {$data}\n";
msg_receive($ip,0,$msgtype,4,$data,false,null,$err);
echo "msgtype {$msgtype} data {$data}\n";
?>
Now run:
in terminal #1 php5 receive.php
in terminal #2 php5 receive.php
in terminal #3 php5 send.php
Showing messages from queue will flip-flop. It means you run once send.php, the message will be shown in terminal #1. Second run it will be in t#2, third #1 and so on.