Segfault has asked for the wisdom of the Perl Monks concerning the following question:

**Warning: Incredibly newbie-ish question**

I recently started playing around with IO::Socket, and I wanted to write a small script to connect to a server, send a given piece of data, and do something when a reply is received.

My question, though, is how do I "wait" for that to happen? I suppose I could use a while loop or something, but isn't that a bit cheezy? How can I do some real event handling in a situation like this?

Thanks

Replies are listed 'Best First'.
Re: Waiting for an event
by bikeNomad (Priest) on Jun 25, 2001 at 07:39 UTC
    The usual answer for this is to use select(), probably via IO::Select (since it's easier and OO). select() will let you wait until something of interest happens on zero or more file handles (including sockets and regular files), or until a timeout. The "something of interest" includes a handle being able to read, write, or having an exceptional condition.

    If you want to see an entire framework built around select (more or less), look at POE.

Re: Waiting for an event
by tachyon (Chancellor) on Jun 25, 2001 at 08:24 UTC

    Here is a typical generic wait for something or timout piece of code. In this case we wait for an exclusive file lock

    my $timeout = 15; # timeout in seconds my $delay = 1; # number of seconds between re-tries open (FILE, ">$file") or die "Unable to create file '$file': $!\n"; my $count = 0; until (flock FILE, LOCK_EX) { sleep $delay; $count += $delay; die "Can't lock file '$file': $!\n" if $count >= $timeout; }

    cheers

    tachyon

Re: Waiting for an event
by pope (Friar) on Jun 25, 2001 at 13:34 UTC
    Yes, as bikeNomad suggested, you can use the four-argument select() or IO::Select. This way avoids the so-called busy-waiting by letting the kernel does the scanning of array of file descriptors of interest. Once your socket is ready to read or write, the kernel wakes up your program, which then handles it. Here's a simple client to send HEAD to a httpd:
    #!/usr/bin/perl -w use IO::Socket; $|++; my $client = IO::Socket::INET->new( PeerAddr => 'www.satunet.com', PeerPort => 80, Proto => 'tcp',) or die "Can't connect: $!"; $rin = $rout = $win = $wout = ''; vec($rin, $client->fileno, 1) = 1; vec($win, $client->fileno, 1) = 1; while (1) { if (select($rout = $rin, $wout = $win, undef, 5) > 0) { if (vec($rout, $client->fileno, 1)) { while (<$client>) { print "Client read: $_" } $client->close; } elsif (vec($wout, $client->fileno, 1)) { print $client "HEAD / HTTP/1.0\r\n\r\n"; } } else { exit } }
    Using IO::Select is much more convenient since it does the bit-vector works behind the curtain, as well as its nice OO interface.

    POE is also good, but it requires you to have some basic knowledge about state machine, otherwise its programming style may be confusing. I'd recommend using JPRIT's Event module if you want to explore the full power of event-driven programming.

Re: Waiting for an event
by Anonymous Monk on Jun 25, 2001 at 22:13 UTC
    or you can do $var=<$socket> That waits until the Socket is ready.(PM's: See this**Warning: Incredibly newbie-ish question** That means he doesn't know that a Socket is like a File)
      But
      $var = <$socket>;
      only works if the data coming into the socket happens to be delimited by newlines. Not all network protocols are newline-delimited.