Yes, you can get fcntl on windows*. As for using it to do non blocking, I have to admit that I've never done it in Perl. But here is how I do it in C, and I suspect that the Perl way is almost identical:
#include <stdio.h>
#include <fcntl.h>
void SetNonBlocking( int filehandle )
{
int fhFlags;
fhFlags = fcntl(filehandle,F_GETFL);
if (fhFlags < 0)
{
perror("fcntl(F_GETFL)");
exit(1);
}
fhFlags |= O_NONBLOCK;
if (fcntl(filehandle,F_SETFL,fhFlags) < 0)
{
perror("fcntl(F_SETFL)");
exit(1);
}
return;
}
Update:
We discover this later in this thread, but rather deep, so I'll reiterate it here. It turns out that the fcntl module is available on Win32, but not fcntl(2) the method. That is *nix specific. Camel2 states, "fcntl will produce a fatal error if used on a machine that doesn't implement fcntl(2)."
My new recomendation is to use select to poll the socket, and when it has data, then read from it blocking. You can simulate non-blocking by using a small timeout on the select and only reading a few charaters (or even just 1) at a time.
*Note that the standard distribution uses the local c compiler to create Fcntl.pm during install. It is possible then, that someone might not have Fcntl.pm, however ActiveState's distribution of Perl does include it.
| [reply] [d/l] |
The point was not to figure out how to do it.. I know how to do it.. Here is my 'test' code.
#!/usr/bin/perl
use IO::Socket;
$sock = IO::Socket::INET->new( PeerAddr => '192.168.0.4',
PeerPort => 4000,
Proto => 'tcp'
);
$flags = fcntl($sock, F_GETFL, 0)
or die "Can't get flags for socket: $!\n";
fcntl($sock, F_SETFL, $flags | O_NONBLOCK)
or die "Can't make socket nonblocking: $!\n";
print $sock "logn 0607daimuntemp123\n";
while(1) {
sleep 1;
$str = <$sock>;
chomp $str;
print $str . "\n";
if( $str =~ /^$/ ) {
print "null\n";
}
}
When run, it results in this error:
fcntl is not implemented at sam.pl line 10.
Daimun | [reply] [d/l] |
use Fcntl;
Easy mistake to make. That should fix it.
Update:
I tried your code (plus the use statement and a few print statements) on my NT box with Perl 5.6 and got this rather annoying message:
Your vendor has not defined Fcntl macro F_GETFL, used at C:\temp.pl li
+ne 10.
That means the Fcntl implementation in my install is incomplete. I suspect this is going to be true across Windows installations, so you might want to write a wrapper around Fcntl that defaults to Fcntl but fills in the holes when they are missing. | [reply] [d/l] [select] |
| [reply] |
Since you are already using Tk, you may be interested
in Tk::Fileevent and Tk::IO.
These give you a more generalized way of handling file and socket i/o in a gui event loop. (Basically placing a select() call for you in the gui event loop, you just supply a callback) Do read the CAVEATS and
WARNINGS sections though.
| [reply] |
have you looked at the can_read function of the IO::Socket class? it accepts a value in seconds to wait before timing out and proceeding with the rest of the script.
for example, this (untested) will wait 1 second and then move on.
my $sel = $sock->select;
$sel->can_read(1);
| [reply] [d/l] |
I can't seem to find any such can_read function in IO::Socket. Do you know of any documentation on it?
Daimun
| [reply] |
| [reply] |
I'd like to thank everyone whom offered help with this dilemma. I've decided the most prudent solution will be usnig a Select, as it will enable me to keep the code fairly unified, with a few simple checks to determine if it's running in a non-posix environment.
- Daimun | [reply] |