in reply to Timeout Socket recv on UDP... on windows

How about using a select based approach? Something like:

...(set up socket)... my $end = time + 15*60; my $rin; vec($rin, fileno($hSocket), 1) = 1; while (1) { my $timeleft = $end - time; last if ($timeleft <= 0); my ($nfound, $t) = select(my $rout = $rin, undef, undef, $timeleft +); last if ($nfound == 0); # either timeout or end of file # read from socket here }

Replies are listed 'Best First'.
Re^2: Timeout Socket recv on UDP... on windows
by shunyun (Novice) on Jan 26, 2008 at 16:15 UTC
    pc88mxer, I gotta look into this more, as I'm not sure what this is doing. Is this checking for whether $hSocket is undef (see my other reply, regarding checking if accept has been called)? I'll plug this in, read up, and try. Not necessarily in that order. Thanks
      The select call will wait $timeleft seconds or until there is data available to be read on the socket, whichever occurs first. This allows you to implement non-blocking I/O.

      This raises a good point: you have a number of tcp and udp sockets. Do you need (or want) to operate them at the same time (i.e. multiplex the I/O)? If so, you can either do that with threads or also with select.

      Final point... select can also be used to determine if a socket is ready to accept an incoming connection.

        Thanks folks. Both the non-blocking and select responses helped. I've got working code now; I ended up not needing to establish non-blocking, as pc88mxer's guidance put me in the right place. Here's my final working routine:

        Sorry that this looks ugly here. click download to see correct format.

        sub ListenOnUDP { my $end = time + $timeout; print "PortListen on $strFQDN ($address) at $strProtocol\/$intList +enPort\n"; # Open a udp port my $hSocket = IO::Socket::INET->new(LocalPort=>$intListenPort, Pro +to=>$strProtocol, Timeout=>$timeout) or die "Can't create UDP socket: $@"; # Wait for a connection ($hSocket is undef until an accept call is + made). my $rin = ''; vec($rin, fileno($hSocket), 1) = 1; while (1) { my $timeleft = $end - time; if ($timeleft <= 0) { print "No connection: Timed out after $timeout seconds.\n" +; last; } my ($nfound, $t) = select(my $rout = $rin, undef, undef, $time +left); if ($nfound == 0) { # either timeout or end of file print "No connection: Timed out after $timeout seconds.\n" +; last; } # Connection exists; Receive data, open a response port, respo +nd, then close both ports. my ($datagram,$flags); while ($hSocket->recv($datagram,42,$flags)) { my $ripaddr = $hSocket->peerhost; my $rport = $hSocket->peerport; print "RECIEVE_FROM-TO, $ripaddr, $strProtocol\/$rport, $a +ddress, $strProtocol\/$intListenPort, message=$datagram\n"; # UDP is connectionless, so try to open a connection going + back the other way, then send a response. # NOTE: This requires a predefined 'remote' port. Pass via + commandline; default is $intSendPort my $hResponseSocket = IO::Socket::INET->new(Proto=>$strPro +tocol,PeerHost=>$ripaddr,PeerPort=>$intSendPort); print "SEND_FROM-TO, $address, $strProtocol\/" . $hRespons +eSocket->sockport . ", $ripaddr, $strProtocol\/$intSendPort, message= +PONG!\n"; $hResponseSocket->send("PONG!"); close($hResponseSocket); last; } last; } close($hSocket); }

        Again, thanks folks, this solved my problem. Anyone interested in helping me QA and test my final script on other platforms?