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

I'm working on a little client/server application. The server does not constantly have a socket open. At regular intervals it opens a socket and listens for a request. Thanks to some advice I got here before, I'm using IO::Select so that I don't block on that socket.

My problem now is that occasionally, when the client sends its udp request, the server does not have the socket open, and an ICMP port unreachable message is sent back to the client. The client dies at this point.

What I want to happen is for the client to resend the request. I'll include the code below.

#!/usr/bin/perl use IO::Socket; foreach $request (@ARGV) { $MAXLEN = 1024; $PORTNO = 5151; $TIMEOUT = 5; #$request = "198.59.115.12:25"; $server_host = "kona.swcp.com"; $sock = IO::Socket::INET->new(Proto => 'udp', PeerPort => $PORTNO, PeerAddr => $server_host) or die "Creating socket: $!\n"; $sock->send($request) or die "send: $!"; eval { local $SIG{ALRM} = sub { die "alarm time out" }; alarm $TIMEOUT; $sock->recv($reply, $MAXLEN) or die "recv: $!"; alarm 0; 1; } or die "recv from $server_host timed out after $TIMEOUT seconds.\n"; print $reply; sleep 5; }

Replies are listed 'Best First'.
Re: don't die, retry
by clintp (Curate) on Aug 05, 2001 at 05:45 UTC
    Instead of (I presume this is where it's failing):
    $sock->send($request) or die "send: $!";
    Try something more along the lines of:
    unless ($_=$sock->send($request)) { die "send: $!" unless $! =~ /unreachable/; # Or whatever sleep 1; }
    Maybe throw a counter in there so it only sleeps/retries a maximum number of times.
Re: don't die, retry
by jepri (Parson) on Aug 05, 2001 at 06:21 UTC
    I've been using something like this:

    #Take five shots at getting an available port foreach ( 1..5 ) { last if $sock->send($request); } return undef unless $sock;

    ____________________
    Jeremy
    I didn't believe in evil until I dated it.

Re: don't die, retry
by Benedict (Initiate) on Aug 08, 2001 at 22:58 UTC

    Thanks for the suggestions. They do not seem to work, however I have a theory why.

    Both of these assume that it is failing at this point:  $sock->send($request) or die "send: $!"; It's not, however. I think this is why. Since I'm using UDP, as long as it actually sends the packets away, it does not die here. If it were a TCP connection, it would fail the handshake and die here, but with UDP it does not seem work that way.

    Very soon after sending, though, it does get the ICMP unreachable error, and the Perl error is actually "Connection Refused". I need to figure out how to trap that error.

    jgentry@swcp.com