Как цикл while() может не останавливаться при использовании fsockopen() и fgets() в PHP?

Это базовый код подключения для небольшого IRC-бота PHP. Проблема в том, что кажется, что цикл while() не выходит за рамки fgets(), пока не получит данные с IRC-сервера. Я хочу, чтобы цикл while() повторялся независимо от того, не отправил ли сервер IRC данные. Это возможно?

$socket = fsockopen($config['irc_server'], $config['port']);
while (1) 
{
    $data = fgets($socket, 128);
    echo '[RECEIVE] ' . $data;
    $recv = explode(' ', $data);

    if ($recv[0] == 'PING')
    {
        send('PONG', $recv[1]);
    }
}

person Equinox    schedule 11.12.2009    source источник


Ответы (4)


Проверьте функции socket_*, включая эту:

socket_set_nonblock

Вы также можете передать неблокирующий флаг в socket_recv

Вот обязательный быстрый и грязный пример (без проверки ошибок)

/* Create a TCP/IP socket. */
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$result = socket_connect($socket, $address, $service_port);
while (false === ($bytes = socket_recv($socket, $buf, 2048, MSG_DONTWAIT))) 
{ /* do stuff while waiting for data */ }
person ChronoFish    schedule 11.12.2009

Взгляните на ftell. Вот связанный пример из документации php:

#!/usr/bin/php4 -q
<?
#following will hang if nothing is piped:
#$sometext = fgets(STDIN, 256)

$tell = ftell(STDIN);

if (is_integer($tell)==true) 
  {echo "Something was piped: ".fread(STDIN,256)."\n";}
else 
  {echo "Nothing was piped\n";}

?>
person Justin Ethier    schedule 11.12.2009

stream_select() может указать, доступны ли данные для чтения в сокете. Но fgets() не возвращается до тех пор, пока не будет разрыва строки или не закончится поток. Поэтому вместо этого вам придется использовать fread() и разделить данные самостоятельно.

кстати: вас также может заинтересовать пакет PEAR::Net_SmartIRC.

person VolkerK    schedule 11.12.2009

Проблема в том, что кажется, что цикл while() не выходит за рамки fgets(), пока не получит данные с IRC-сервера.

Я не вижу в этом проблемы. Что вы хотите, чтобы этот код делал, если он ничего не получает?

На данный момент он просто снова вернется к fgets, так что вы просто сжигаете циклы, занятые ожиданием без уважительной причины. Блокировка является правильным поведением в этом случае.

person Anon.    schedule 11.12.2009
comment
Возможно, он мог бы захотеть, чтобы бот периодически что-то говорил, даже если он не получает никакой информации. Подумайте, например, о тех ботах-пустяках. Даже если в комнате тишина, они задают новый вопрос каждые 60 секунд или что-то в этом роде. Точно так же боты DCC часто рекламируют себя каждые несколько минут. - person Frank Farmer; 11.12.2009