On Fri, 2021-10-01 at 17:01 -0500, Andy Bach wrote:
> > If the signal would be caught, I could handle the error and try to
> reconnect, or, if that also fails, do something else.
> 
> Oh. I was thinking you wanted it to check the connection before trying to
> print. Well, the print stmt returning undef will tell you the same thing.

I tried that, and print didn't return undef.

Let's see, we need a better example here ...


#!/usr/bin/perl

use strict;
use warnings;
use utf8;
use IO::Socket::INET;

my $addr = '192.168.33.33'; # use an address not in use
my $socket = new IO::Socket::INET(
                                  PeerAddr => $addr,
                                  PeerPort => 32768,
                                  Proto => 'udp',
                                  Timeout => 2
                                 ) or die "Can't bind : $@\n";
if(defined($socket)) {
  if($socket->connected) {
    print "socket is connected\n";
  } else {
    print "socket NOT connected\n";
    exit;
  }
  my $status = print $socket "test\n";
  printf("status: %s\n", defined($status) ? $status : '[undef]');
  $socket->close;
} else {
  print "socket not defined\n";
}


When I run this:


./sockettest.pl
socket is connected
status: 1


That clearly shows what I mean.  How can I tell if the print was successful
or not?  It kinda makes sense, too, because it /could/ mean that the data
was sucessfully sent.  Without a receiver or monitoring the traffic, I don't
know.

Is it even necessary to reconnect?  It seems evident that there is no way to
tell if sending some UDP packet(s) to some address and port will be received
because UDP is stateless.  The only way to know if the commands I'm sending
to the realais is to receive the acknowledgement from the relais or to ask
the relais about its status.

So why does print say that the file is not open?  How did that happen?

It seemed to me that once I had unplugged the network cable and plugged
it back in, my program did not resume but kept saying it can't print to a
closed socket.  That would require to re-open the socket (file) and I need
to know when that needs to be done.

Otherwise, I would need to keep the socket closed, and would have to open
and close it every time I want to print or receive data over it.  That seems
inconvenient.

I think I need to write a listener:


#!/usr/bin/perl

use strict;
use warnings;
use utf8;
use IO::Socket::INET;

my $addr = 'sender.example.com'; # adjust as needed
my $socket = new IO::Socket::INET(
                                  PeerAddr => $addr,
                                  PeerPort => 32768,
                                  Proto => 'udp',
                                  Timeout => 200
                                 ) or die "Can't bind : $@\n";
if(defined($socket)) {
  if($socket->connected) {
    print "socket is connected\n";
  } else {
    print "socket NOT connected\n";
    exit;
  }
  eval {
    my $datagram = undef;
    my $flags;
    local $SIG{ALRM} = sub { die "alarm\n" };
    alarm(20);

    while (1) {
      my $status = $socket->recv($datagram, 1400, $flags);
      if(defined($status)) {
        printf(
               "INFO: datagram from %s, flags %d, data: '%s' (%s), status: 
%s\n",
               $socket->peerhost,
               $flags || 0,
               unpack("h32", $datagram),
               $datagram,
               $status
              );
        last;
      } else {
        print "status undefined\n";
      }
    }

    alarm(0);
  };
  if ($@) {
    print "recv timeout\n"
  }

  $socket->close;
} else {
  print "socket not defined\n";
}


Unfortunately, that doesn't receive anything.  I have verified with netcat
that the connection between the two hosts is possible.  The listener
doesn't receive anything from netcat, either.

How can that be?  My program for the relais works the same, and it does
receive data from the relais.

> Hmm, it would appear printing to a closed file handle *doesn't* (doesn't
> always?) throw a SIGPIPE. I set the signal handler
> $ perl -wE 'use strict; $SIG{"PIPE"} = sub { die "pipe\n" }; open(OUT, ">",
> "/tmp/out"); close OUT ;my $res = print OUT "hi mom\n"; say $res'
> print() on closed filehandle OUT at -e line 1.
> Use of uninitialized value $res in say at -e line 2.
> $
> 
> So, I added a sleep and sent a SIGPIPE to the job:
> $ perl -wE 'use strict; $SIG{"PIPE"} = sub { die "pipe\n" }; open(OUT, ">",
> "/tmp/out"); close OUT ;my $res = print OUT "hi  mom\n"; say $res; sleep
> 10'&
> [1] 36594
>   print() on closed filehandle OUT at -e line 1.
>   Use of uninitialized value $res in say at -e line 2.
> 
> $ kill -SIGPIPE 36594
> pipe
> $

Right, so that doesn't work, either.



-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to