Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Сеть > ожидание ответа функции fgets


Автор: maykoff 9.1.2008, 19:29
Код:
Код

$f = fopen("/dev/xxxx","a+");
fputs($f,"AT\r\n");
for(;!feof($f);)
{
    $str = fgets($f,8);
    echo "$str";
    if(preg_match("/OK\r\n/",$str)) break;
}
fclose($f);


/dev/xxxx - это компорт, на котором висит GSM-шлюз.
В консоли это выглядит так:

AT - запрос
OK - ответ

Проблема в том, что конца файла у $f, похоже , просто нет.
Прочитав всё что можно, на строке $str = fgets($f,8); зависает, ожидая дальнейшего вывода, которого нет, до выхода по условию цикла дело не доходит.

Как вариант - задать (сэмулировать) таймаут для функции, в которую поместить чтение из указателя.
Но как это сделать - пока не придумал.

Идею с отдельным исполняемым скриптом держу про запас.

Если у кого какие соображения на этот счёт будут - заранее благодарен .

P.S. Прошу не посылать на тему "Виснет скрипт на fgets" - смотрел - там эта проблема не решена, её просто обошли.

Мне именно нужно избежать (не допустить) зависания в случае нестандартного (непредвиденного ) ответа шлюза.

Автор: sTa1kEr 11.1.2008, 19:03
Используйте http://ru2.php.net/manual/ru/function.stream-set-timeout.php. Тогда по достижению заданного таймаута fgets() будет "отпускать" скрипт.
Код

$f = fopen("/dev/xxxx","a+");
stream_set_timeout($f, 5);
fputs($f,"AT\r\n");
for(;!feof($f);)
{
    $str = fgets($f,8);
    echo "$str";
    if(preg_match("/OK\r\n/",$str)) break;
}
fclose($f);

Автор: maykoff 12.1.2008, 00:00
Не факт, что сработает, но спасибо, завтра попробую. Спасибо.

Нет ли способа проверит состояние открытого потока? В частности - проверить , все ли байты из него вычитаны или количество невычитанных байтов.

И ещё - подходит ли для этой задачи fopen ? Или есть более подходящие функции?

Автор: FractalizeR 12.1.2008, 17:31
http://www.php.net/stream_get_meta_data

Думаю, fopen подходит вполне

Автор: maykoff 12.1.2008, 23:12
Проблему обойти удалось путём тщательного анализа ответа шлюза (по ответу можно определить последний байт),  но академический интерес остаётся - как избежать зависания скрипта при попытке вычитать несуществующий байт из потока...

Автор: FractalizeR 13.1.2008, 01:53
Я же говорю - вызвать stream_get_meta_data и посмотреть, сколько байт находится в буфере непрочитанных. Вы документацию по моей ссылке смотрели?

Автор: maykoff 13.1.2008, 12:52
sTa1kEr, поюзал stream_set_timeout($f, 5); - как и ожидалось - не сработало. 

Автор: maykoff 13.1.2008, 13:52
FractalizeR, смотрел.
Цитата

unread_bytes (int) - the number of bytes currently contained in the PHP's own internal buffer. 
Note: You shouldn't use this value in a script.

Вот код (sleep`ы убрал, чтоб не захламлять):
Код

$f = fopen(config::COMPORT,"a+");       //открываю компорт
print_r(stream_get_meta_data($f));     //смотрю состояние
fputs($f,"AT\r\n");                                  //подаю команду, типичный ответ - ОК
print_r(stream_get_meta_data($f));     //смотрю состояние
for($i=0,$z='';;$i++)                              //вычитываю все данные из потока
{
    $s = fgetc($f);                                   //посимвольно (байтами)
    $s = base_convert(ord($s),10,16);   //для отображения непечатных символов
    if(strlen($s) == 1) $s = "0$s";           //для красоты
    $z.= $s;
    echo $i." ".$s." $z\r\n";                     //вывожу
}


Вот вывод:
Код

Array
(
    [wrapper_type] => plainfile
    [stream_type] => STDIO
    [mode] => a+
    [unread_bytes] => 0
    [seekable] => 1
    [uri] => /dev/cuaa0
    [timed_out] =>
    [blocked] => 1
    [eof] =>
)
Array
(
    [wrapper_type] => plainfile
    [stream_type] => STDIO
    [mode] => a+
    [unread_bytes] => 0
    [seekable] => 1
    [uri] => /dev/cuaa0
    [timed_out] =>
    [blocked] => 1
    [eof] =>
)
0 41 41
1 54 4154
2 0d 41540d
3 0d 41540d0d
4 0a 41540d0d0a
5 4f 41540d0d0a4f
6 4b 41540d0d0a4f4b
7 0d 41540d0d0a4f4b0d
8 0a 41540d0d0a4f4b0d0a
9 f8 41540d0d0a4f4b0d0af8

Скрипт работу не закончил - завис.
Расшифровка вывода - примерно 
AT
OK

f8 - левый какой-то байт, он присутствует в каждом ответе один раз (иногда - на разных позициях, но прогнозируемо)

Как видно - Количество байт в сокете не отображено, да и не рекомендуется этот параметр к использованию.

Если есть соображения по этому поводу - с удовольствием выслушаю smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)