Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Non-blocking Socket support for Win32

151 views
Skip to first unread message

Robert Moser II

unread,
Jul 5, 2003, 5:14:29 PM7/5/03
to Perl5 Porters
It seems to me that there isn't a whole lot that needs to be changed to
provide non-blocking support for Win32 systems from within the
IO::Socket module. Of course I could be missing something.

There needs to be a blocking() sub which uses ioctl() instead of
allowing IO:Handle's blocking sub to do the work. And some of the if
conditions in the connect() function need to be changed to reflect the
fact that Windows uses EWOULDBLOCK instead of EINPROGRESS and WSAEINVAL
(10022) instead of EISCONN.

Note that the following are based on the IO::Socket which came with
ActiveState Perl 5.8.0 build 806. Also note that the blocking() sub
doesn't handle the case of just checking the blocking state of a socket
using $somesock->blocking().

Here is a blocking sub which would work (assuming that the fixed version
of ioctl from change 19534 is being used):

sub blocking {
my $sock = shift;
return $sock->SUPER::blocking(@_) unless $^O =~ /Win32/;
#Windows handles blocking differently
my $nonblocking = $_[0] ? "0" : "1";
#0x8004667e is FIONBIO
return ioctl($sock, 0x8004667e, \$nonblocking);
}

and here is the modified connect (sorry this isn't a diff)

sub connect {
@_ == 2 or croak 'usage: $sock->connect(NAME)';
my $sock = shift;
my $addr = shift;
my $timeout = ${*$sock}{'io_socket_timeout'};
my $err;
my $blocking;

$blocking = $sock->blocking(0) if $timeout;
if (!connect($sock, $addr)) {
if (defined $timeout && ($!{EINPROGRESS} || ($^O =~ /Win32/ &&
$!{EWOULDBLOCK}))) {
require IO::Select;

my $sel = new IO::Select $sock;

if (!$sel->can_write($timeout)) {
$err = $! || (exists &Errno::ETIMEDOUT ? &Errno::ETIMEDOUT : 1);
$@ = "connect: timeout";
}
elsif (!connect($sock,$addr) && not ($!{EISCONN} || ($^O =~
/Win32/ && $! == 10022))) {
# Some systems refuse to re-connect() to
# an already open socket and set errno to EISCONN.
# Windows sets errno to WSAEINVAL (10022)
$err = $!;
$@ = "connect: $!";
}
}
elsif ($blocking || !($!{EINPROGRESS} || ($^O =~ /Win32/ &&
$!{EWOULDBLOCK}))) {
$err = $!;
$@ = "connect: $!";
}
}

$sock->blocking(1) if $blocking;

$! = $err if $err;

$err ? undef : $sock;
}

Benjamin Goldberg

unread,
Jul 7, 2003, 7:27:11 PM7/7/03
to Robert Moser II, p5p
Robert Moser II wrote:
>
> It seems to me that there isn't a whole lot that needs to be changed to
> provide non-blocking support for Win32 systems from within the
> IO::Socket module. Of course I could be missing something.
>
> There needs to be a blocking() sub which uses ioctl() instead of
> allowing IO:Handle's blocking sub to do the work. And some of the if
> conditions in the connect() function need to be changed to reflect the
> fact that Windows uses EWOULDBLOCK instead of EINPROGRESS and WSAEINVAL
> (10022) instead of EISCONN.

According to my network programming book, both EWOULDBLOCK and
EINPROGRESS are valid errno values for a nonblocking connect.

However, the fact that neither of these two constants are in Errno.pm
probably should be considered a bug. (At least, they aren't there
in Activestate Perl 5.6.1, with local patch 631)

--
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "$@[$a%6
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}

Robert Moser II

unread,
Jul 9, 2003, 12:00:27 AM7/9/03
to Benjamin Goldberg, p5p

Benjamin Goldberg wrote:


> Robert Moser II wrote:
>
>>There needs to be a blocking() sub which uses ioctl() instead of
>>allowing IO:Handle's blocking sub to do the work. And some of the if
>>conditions in the connect() function need to be changed to reflect the
>>fact that Windows uses EWOULDBLOCK instead of EINPROGRESS and WSAEINVAL
>>(10022) instead of EISCONN.
>
> According to my network programming book, both EWOULDBLOCK and
> EINPROGRESS are valid errno values for a nonblocking connect.

With that being the case, the "$^O =~ /Win32/ &&" portions could be
dropped to make it a bit cleaner. It just seems like Windows is the
only one where EWOULDBLOCK is used. The bit with WSAEINVAL is a bit
harder to simplify, since no other platform has that particular error.


> However, the fact that neither of these two constants are in Errno.pm
> probably should be considered a bug. (At least, they aren't there
> in Activestate Perl 5.6.1, with local patch 631)

And they still aren't there in ActivePerl 5.6.1.635. However, they are
present in ActivePerl 5.8.0.806, which is what I based my changes on. I
also seem to recall something about the $!{ERROR} construction not being
valid in 5.6.1. There doesn't seem to be anything majorly different
between the 5.8.0.806 and 5.6.1.635 versions of Errno.pm other than the
addition of about 37 error numbers, mostly networking related, so maybe
if a 5.6.1.636 build is released, those constants could be in there.


Nick Ing-Simmons

unread,
Jul 9, 2003, 4:00:31 AM7/9/03
to rlm...@earthlink.net, Benjamin Goldberg, p5p
Robert Moser II <rlm...@earthlink.net> writes:
>Benjamin Goldberg wrote:
>> Robert Moser II wrote:
>>
>>>There needs to be a blocking() sub which uses ioctl() instead of
>>>allowing IO:Handle's blocking sub to do the work. And some of the if
>>>conditions in the connect() function need to be changed to reflect the
>>>fact that Windows uses EWOULDBLOCK instead of EINPROGRESS and WSAEINVAL
>>>(10022) instead of EISCONN.
>>
>> According to my network programming book, both EWOULDBLOCK and
>> EINPROGRESS are valid errno values for a nonblocking connect.
>
>With that being the case, the "$^O =~ /Win32/ &&" portions could be
>dropped to make it a bit cleaner. It just seems like Windows is the
>only one where EWOULDBLOCK is used. The bit with WSAEINVAL is a bit
>harder to simplify, since no other platform has that particular error.

WSAEINVAL is just Win32 bolt-on for EINVAL from sockets DLL.

--
Nick Ing-Simmons
http://www.ni-s.u-net.com/

Robert Moser II

unread,
Jul 10, 2003, 2:12:03 AM7/10/03
to Nick Ing-Simmons, Benjamin Goldberg, p5p
Nick Ing-Simmons wrote:
>
> WSAEINVAL is just Win32 bolt-on for EINVAL from sockets DLL.
>

That is mostly true. Note that WSAEINVAL != EINVAL though. WSAEINVAL ==
10022 and EINVAL == 22.

Nick Ing-Simmons

unread,
Jul 10, 2003, 6:44:42 AM7/10/03
to rlm...@earthlink.net, Nick Ing-Simmons, goldberg@hotpop.com Benjamin Goldberg, p5p
Robert Moser II <rlm...@earthlink.net> writes:

I see no pattern there it is not as though 10000 is a round number ;-)

That is the trouble with "bolt ons" - the bolt-heads are there to scrape
your shins on...

You must remember that back in '90s networks were optional on PCs
so Win32 did not need them to be tightly integrated ;-)

0 new messages