Read up on select() and have a look at IO::Select. In particular, have a look at the IO::Select's can_read() method. It will do what you want. You just have to specify a timeout.
-sauoq
"My two cents aren't worth a dime.";
| [reply] [Watch: Dir/Any] |
If that does not offer exactly what you are looking for, what I have always done (in other languages, never had to do sockets with perl) was create a thread to handle the information.
Attach a buffer and every now and again read the buffer to see what is in it from your main loop.
This assumes you have thread support compiled into your version of perl (My Admin at work is doing this very thing right now to solve a similar problem)
| [reply] [Watch: Dir/Any] |
Although threads are fun, using a thread to manage a socket is overkill. You can do just fine using IO::Select and a single process. UNIX people have been writing single-process socket handling applications for years, and they work very well.
The problem with introducing threads is that you have to make sure your code is thread safe. As soon as you put two trains on the metaphorical track of your program, you're going to have to make sure you're not setting yourself up for disaster.
| [reply] [Watch: Dir/Any] |
If you want to timeout the client request, you could wrap it in an eval,
eval {
local $SIG{ALRM} = sub { die "Timed Out" };
alarm 10;
### IO::Socket/Select function call goes here
alarm 0;
};
if ($@ and $@ !~ /Timed Out/) {
die
}
this should give you a 10 second timeout on your function call.
--
hiseldl
| [reply] [Watch: Dir/Any] [d/l] |
It might be smarter to save the old signal value outside the eval, and restore it after the eval. Yes, setting it local works fine. I totally agree with that much.
If the eval crashes on any code between your alarm 10 and alarm 0, the eval breaks. Granted, you have code to check for errors, but if people don't check, you can get some really bizzare errors on things such as cgi's with apache.
I saw code that never hit the alarm 0 'cause the eval died (no, not die()) on a particular line, and bailed on the eval, causing processing to die randomly due to the alarm never being reset :)
| [reply] [Watch: Dir/Any] |
You probably need to use IO::Select, and the alarm too. Take a look in this example for select, to see how to use it. This example show how to read in the same time 2 sockets, without stop another:
#!/usr/bin/perl
## Open the 2 socket connections:
my $sock1 = new IO::Socket::INET(
PeerAddr => host1 ,
PeerPort => 6622 ,
Proto => 'tcp',
Timeout => 30) ;
my $sock2 = new IO::Socket::INET(
PeerAddr => host2 ,
PeerPort => 6622 ,
Proto => 'tcp',
Timeout => 30) ;
## Crete the interface for select, with the 2 sockets:
my $can_read = IO::Select->new( $sock1 , $sock2 );
## File to log the data:
open (LOG,"./log.txt") ;
## Here the select interface will return to the array
## @has_buf the $sockets with data in the buffer, using
## 1s of delay:
while( my @has_buf = $can_read->can_read(1) ) {
foreach my $has_buf_i ( @has_buf ) { ## $has_buf_i is one of the
+ sockets
my $buffer ;
## Create another select to can read byte by byte, because
## we just know that the socket have data, but not the length:
my $sel = IO::Select->new($has_buf_i) ;
## Read byte by byte:
while( $sel->can_read(0.1) ) {
sysread($has_buf_i, $buffer , 1 , length($buffer) ) ;
}
## Print to the log file:
if ($buffer ne '') { print LOG $buffer ;}
}
}
exit;
"The creativity is the expression of the liberty". | [reply] [Watch: Dir/Any] [d/l] |
Although I don't have the time (or memory) to give you code, you should look into the whole non-blocking I/O beastiary. When you get down to it, non-blocking I/O is simply the ability to check for new data / write new data without having to wait for the operation to finish. That is exactly what you want. | [reply] [Watch: Dir/Any] |
You need to use the select() statement. Look in the man pages for an example. | [reply] [Watch: Dir/Any] |