2013-12-19 2 views
7

Решения в конце вопроса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, но она зависает, ожидая появления первых нескольких байтов (а не в конце), которые могут быть установлены на задержку сети и другие нормальные факторы.

ответ

5

говорит «stream_get_contents() работает на уже открытом потоке ресурс и возвращает оставшееся содержимое в строке, до MAXLENGTH байт и, начиная с указанным смещением «.

поэтому, когда вы предоставляете 5 как максимальную длину, он будет читать только до пяти байтов и продолжает. если он не могу дочитать до 5 байт ll `ждать и истекает через 10 секунд, которые вы упомянули в stream_set_timeout

пример:

//server side statement<br/> 
$data = stream_get_contents($this->socket, 5); 

//corresponding client code<br/> 
fwrite($client, "1234"); 

в вышеописанном случае сервер будет ждать, пока вы написать еще один байт fwrite($client, "5");

+0

Вы сэр - спасатель! Это было точно проблема. Я опубликую свое рабочее решение выше для кого-либо еще с этой проблемой. – gb056

1

Я предлагаю вам использовать функцию sleep($seconds) или даже функцию usleep($nanoseconds). Таймаут устанавливается для самого потока, а не для каждой документации stream_get_contents

+0

Вы имеете в виду использование 'sleep' для таймаута? Как это будет работать? 'stream_set_timeout' означался как резервная копия, если сервер не отвечал своевременно, поэтому пользователь не остался ждать. – gb056

+0

Вы все равно должны использовать 'stream_set_timeout' на всякий случай, когда сервер зависает. Но между каждым запросом/ответом вы можете использовать 'sleep (10)', чтобы сценарий мог ждать 10 секунд, прежде чем обрабатывать следующий запрос/ответ. –

+0

Код ожидает только один ответ, цикл должен был удостовериться, что он получил весь ответ перед продолжением. Конечно, мне не нужно спать между чтением ** частей ** сообщения? Я все равно попробую и посмотрю, поможет ли это. Обновите вопрос, чтобы он понял, что код ожидает только одного сообщения. – gb056

 Смежные вопросы

  • Нет связанных вопросов^_^