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), чтобы обозначить конец сообщения, поэтому я также останавливаюсь, если я нажму это, а не просто конец потока.

Я делаю что-то неправильно? Есть ли лучший способ сделать это?

Заранее спасибо...

Изменить: просто чтобы быть ясно, приведенный выше код ожидает только один ответ на сообщение. Он не заботится о каких-либо данных, которые возвращаются после получения байта ETX.

Edit2: зависания были видны до 40 секунд сейчас. Кажется, он не фиксируется на 10 секундах, но, как ни странно, каждый раз это хорошие круглые числа.

Решение (спасибо чатсу):

stream_get_contents($stream, $bytes) будет блокировать, пока не получит$bytes байты или время ожидания истекло. Это означает, что мой код достиг конца и пытался прочитать 5 байтов (которых не было), поэтому он ждал 10 секунд, прежде чем сдаться.

Поскольку я знаю, что минимальный размер сообщения, возвращающегося мне, составляет 49 байт, я сначала читаю эти 49 байт (блокировка, пока я не получу их или не истечет 10 с), чтобы заполнитьstream_get_meta_data«sunread_bytes поле. После этого я динамически настраиваю размер буфераmin(16*1024, unread_bytes) поэтому я либо читаю 16k за раз, либо все оставшиеся байты, в зависимости от того, что меньше. В моем случае это обычно означает, что два цикла проходят, так как сообщения часто крошечные (49 байт + полезная нагрузка).

Теперь система зависает в течение приблизительно 3 секунд вместо 10, но она зависает в ожидании поступления первых нескольких байтов (а не в конце), которые могут быть отнесены к задержке сети и другим нормальным факторам.

Ответы на вопрос(2)

Ваш ответ на вопрос