Как цикълът while() може да не блокира, когато използвате fsockopen() и fgets() в PHP?

Това е основният код за връзка за малък PHP IRC бот. Проблемът е, че изглежда, че цикълът 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