Решения в конце вопросаPHP stream_get_contents висит в конце потока
Я пишу PHP приложение, которое отправляет сообщение на сервер, а затем считывает ответ обратно в использовании stream_get_contents
. Таким же образом я общаюсь с тем же сервером в приложении Android. Приложение Android отлично работает и быстро реагирует, однако PHP зависает при чтении ответа с сервера.
В приведенном ниже примере кода я установил крошечный размер буфера 5 байтов для проверки теории. Если удалить этот размер буфера он висит, однако с размером 5 байт он висит только на последнем проходе через петлю:
stream_set_timeout($this->socket, 10); //10 seconds read timeout
while (!feof($this->socket)) {
$breakOut = false;
echo 'Reading response'.time().'<br/>';
$data = stream_get_contents($this->socket, 5);
echo 'Read response'.time().'<br/>';
if ($data === false) {
$this->latestErrStr = "Timed out waiting for a response.";
return false;
} else {
$index = strpos($data, chr(3));
if ($index !== FALSE){
$breakOut = true;
$data = substr($data, 0, $index);
}
$response .= $data;
}
$stream_meta_data = stream_get_meta_data($this->socket);
//If we have no EOF marker then break if there are no bytes left to read
if($breakOut || $stream_meta_data['unread_bytes'] <= 0) {
break;
}
}
Выход следующим образом:
Reading response1387463602
Read response1387463603
Reading response1387463603
Read response1387463603
Reading response1387463603
Read response1387463603
Reading response1387463603
Read response1387463603
Reading response1387463603
Read response1387463603
Reading response1387463603
Read response1387463603
Reading response1387463603
Read response1387463603
Reading response1387463603
Read response1387463603
Reading response1387463603
Read response1387463603
Reading response1387463603
Read response1387463603
Reading response1387463603
Read response1387463603
Reading response1387463603
Read response1387463603
Reading response1387463603
Read response1387463623
Как вы можете видеть существует 10-секундная задержка между двумя последними линиями, но между ними нет заметной задержки.
Также для вашей информации я использую маркер ETX (3), чтобы обозначить конец сообщения, поэтому я также останавливаюсь, если я ударил его, а не только конец потока.
Я что-то не так? Есть ли лучший способ сделать это?
Заранее спасибо ...
Edit: Просто чтобы быть ясно, приведенный выше код только ожидает один ответ на сообщение. Он не заботится о каких-либо данных, которые возвращаются после получения байта ETX.
Edit2: Hangs видели до 40 секунд. Кажется, что он не фиксирован на 10 секунд, но это странно кажется приятным круглым числом каждый раз.
Решение (благодаря chathux) :
stream_get_contents($stream, $bytes)
будет блокировать до тех пор, пока не получит $bytes
байт или тайм-аут истекает. Это означает, что мой код доходил до конца и пытался прочитать 5 байтов (которых не было), поэтому он ожидал 10 секунд, прежде чем сдаться.
Как я знаю, минимальный размер сообщения, возвращающегося ко мне, составляет 49 байт, я сначала прочитал эти 49 байт (блокировка до тех пор, пока я не получу их или не истечет 10 лет), чтобы заполнить поле . После этого я динамически изменяю размер буфера до min(16*1024, unread_bytes)
, поэтому я либо читаю 16k за один раз, либо все остальные байты, в зависимости от того, что меньше. В моем случае это обычно означает только, что два проходят через цикл, поскольку сообщения часто крошечные (49 байтов + полезная нагрузка).
Система теперь висит в течение приблизительно 3 секунд вместо 10, но она зависает, ожидая появления первых нескольких байтов (а не в конце), которые могут быть установлены на задержку сети и другие нормальные факторы.
Вы сэр - спасатель! Это было точно проблема. Я опубликую свое рабочее решение выше для кого-либо еще с этой проблемой. – gb056