views:

269

answers:

2

I've this little script which does it's job pretty well but sometimes it tends to fail. It fails in 2 cases:

  1. with error send: Cannot determine peer address at ./tcp-new.pl line 52

  2. with no output or anything, it just fails to deliver what it got to connected Tcp Client. Usually it happens after I disconnect from server, go home and connect it again. To fix this restart is required and it starts working. Sometimes this problem is followed by problem mentioned in point 1.

Note: it's not problem when I disconnect and reconnect to it again within short amount of time (unless error nr 1 happens).

So can anyone help me make this code be a bit more stable so I don't have to restart it every day?

#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket;
use IO::Select;

my $tcp_port = "10008";
my $udp_port = "2099";

my $tcp_socket = IO::Socket::INET->new(
  Listen => SOMAXCONN,  LocalPort => $tcp_port,
  Proto  => 'tcp',      ReuseAddr => 1,
);
my $udp_socket = IO::Socket::INET->new(
  LocalPort => $udp_port, Proto => 'udp',
);

my $read_select  = IO::Select->new();
my $write_select = IO::Select->new();

$read_select->add($tcp_socket);
$read_select->add($udp_socket);

while (1) {
  my @read = $read_select->can_read();

  foreach my $read (@read) {

    if ($read == $tcp_socket) {

        my $new_tcp = $read->accept();
        $write_select->add($new_tcp);

    } elsif ($read == $udp_socket) {

        my $recv_buffer;
        $udp_socket->recv($recv_buffer, 1024, undef);

        my @write = $write_select->can_write();
        foreach my $write (@write) {
            $write->send($recv_buffer);
        }
    }
  }
}
+2  A: 

The Cannot determine peer address error means that the getpeername() returned false. This probably means that the socket has been closed from the other side, possibly between the can_write() call and the send call. You should probably remove it from the select set and move on.

Leon Timmermans
Can you be more specific about how could i achieve this. I am not that experienced with perl and tcp/udp select so i hear what you are saying but not sure how to implement that.
MadBoy
A: 

In the scenario where your script fails outright, without any error messages, it is probably due to an unhandled signal, usually a SIGPIPE. This can happen if socket operation gets a signal during a send operation. I can reproduce it easily enough in my own systems by simulating many high data volume concurrent connections to a tcp server and simultaneously killing those client connections. Run strace on your script, and you can see the signal clearly enough. That said, I'm trying to figure out how to reproduce the "Cannot determine peer address" error but to no avail....

Gearoid Murphy
So what you are actually saying? That you want to have the same problem as i do ? :)
MadBoy
I need to be able to reproduce the error on demand so I can implement robust automated tests for my code.
Gearoid Murphy