views:

373

answers:

4

This is the basic connection code for a small PHP IRC bot. The problem is that it seems that the while() loop does not progress beyond fgets() until it receives data from the IRC server. I want the while() loop to iterate regardless if the IRC server has not yet sent data. Is this possible?

$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]);
 }
}
A: 

The problem is that it seems that the while() loop does not progress beyond fgets() until it receives data from the IRC server.

I don't see how that's a problem. What do you want that code to do if it receives nothing?

At the moment, it'll just loop around back to the fgets again, so you're just burning cycles busy-waiting for no good reason. Blocking is the correct behaviour in this instance.

Anon.
He could, conceivably, want the bot to say something periodically, even when it receives no input. Think of, for example, those trivia bots. Even if the room's silent, they ask a new question every 60 seconds, or whatever. Similarly, DCC bots often advertise themselves every few minutes.
Frank Farmer
A: 

Take a look at ftell. Here is a related example from the php documentation:

#!/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";}

?>
Justin Ethier
A: 

stream_select() can tell if data is available for reading on the socket. But fgets() doesn't return until there's a line break or the stream ends. So you'd have to use fread() instead and split the data yourself.

btw: You might also be interested in the PEAR::Net_SmartIRC package.

VolkerK
+2  A: 

Check out the socket_* functions including this one:

socket_set_nonblock

You can can also pass a non-block flag to socket_recv

Here is the obligatory quick and dirty example (no error checking)

/* 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 */ }
ChronoFish