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

Greetings,

I am trying to use Perl to communicate over Ethernet sockets using quad port cards. I have several problems. Here is what I am doing in what I hope is a logical sequence.

FINAL GOAL: Use Perl to communicate over UDP or TCP/IP to Linux boxes. Each box will have one or more Adaptec ANA-6944A/TX quad port NIC cards. Almost all box to box communication will be through the quad port NIC cards, but some may be through the port on the motherboard.

INITIAL GOAL: Set up one box with quad port cards and use Perl to communicate from one port to another. Program should not get hung if there is a communication failure.

SO FAR:
1) Cards physically installed in box.
2) Ubuntu 6.10 Desktop installed from CD
3) Updates installed over internet
4) Various utility packages installed from internet using “apt-get install”.
5) Addresses manually assigned to ports via SYSTEM -> ADMINISTRATION -> NETWORKING.
6) Ports activated via a root command line. Sample: ifup eth8.

NOW: focus on only eth8 & eth10 (picked at random)

eth8 was assigned 192.168.21.28
eth10 was assigned 192.168.22.30

I expect routing problems, but I also expect that with a good route set up I should be ok. At this point I charge forward to see how far I can go. My program is:

====================================================================== #!/usr/bin/perl # FILE: try_socket_perl_monks.pl # use warnings; use strict; print "PROGRAM: try_socket_perl_monks.pl \$ARGV[0]=$ARGV[0]\n"; my $MySocket; # socket my $t; # time use IO::Socket; if ($ARGV[0] eq "A") { $MySocket=new IO::Socket::INET->new(Proto => 'udp', PeerAddr=> '192.168.22.30', PeerPort=>8005, LocalAddr=> '192.168.21.28', LocalPort=>8006); print "Configuration A, \$MySocket=$MySocket\n"; } elsif($ARGV[0] eq "B") { my $MySocket=new IO::Socket::INET->new(Proto => 'udp', PeerAddr=> '192.168.21.28', PeerPort=>8006, LocalAddr=> '192.168.22.30', LocalPort=>8005); print "Configuration B, \$MySocket=$MySocket \n"; } elsif($ARGV[0] eq "C") { my $MySocket=new IO::Socket::INET->new(Proto => 'udp', PeerAddr=> '192.168.20.223', PeerPort=>8006, LocalAddr=> '192.168.21.28', LocalPort=>8005); print "Configuration C, \$MySocket=$MySocket \n"; } else { print "Passed argument error \n"; } if (defined($MySocket)) { print "\$MySocket = $MySocket\n"; } else { print "\$MySocket not defined\n"; } my $msg = "This is a test message 123456789012345678901234567890123456 +78901234567890\n"; $MySocket->send($msg); $MySocket->send($msg); $MySocket->send($msg); $MySocket->send($msg); print "After the sending of the message\n"; my $text; my $more = 1; my $retries = 0; do { eval { local $SIG{ALRM} = sub{++$retries and die "timeout\n" }; alarm(3); $retries++; print "above the recv, \$retries=$retries\n"; $MySocket->recv($text, 128) or die "recv failed: $!"; alarm(0); print "\$retries=$retries, length(\$text)=" . length($text) . + "\n"; }; print "retrying \$retries=$retries\n"; } while $retries < 4; print "END OF PROGRAM\n\n";

My first run should be from one port on the quad card to another port on the quad card. The results are:

PROGRAM: try_socket_perl_monks.pl $ARGV[0]=A Configuration A, $MySocket=IO::Socket::INET=GLOB(0x818416c) $MySocket = IO::Socket::INET=GLOB(0x818416c) After the sending of the message above the recv, $retries=1 retrying $retries=2 above the recv, $retries=3 retrying $retries=4 END OF PROGRAM

This did not get stuck (GOOD!!!) but the hub lights did not blink (bad but not totally unexpected).

My second run should be using the same ports on the quad card as my first run, but the ports are reversed. The results are:

PROGRAM: try_socket_perl_monks.pl $ARGV[0]=B Configuration B, $MySocket=IO::Socket::INET=GLOB(0x81842e4) $MySocket not defined Can't call method "send" on an undefined value at ./try_socket_perl_mo +nks.pl line 59

Here is where everything falls apart far worse than I expected. I see no reason why the first run and the second run didn’t have the exact same degree of success or failure.

My third run was to another machine. The other machine did not have code to receive and/or reply to this message, but the other machine was outside this linux box and therefore I would expect routing issues to be resolved. The results of my third run are:

PROGRAM: try_socket_perl_monks.pl $ARGV[0]=C Configuration C, $MySocket=IO::Socket::INET=GLOB(0x81842e4) $MySocket not defined Can't call method "send" on an undefined value at ./try_socket_perl_mo +nks.pl line 59

Once again, failure.

I went through many iterations of “route add” and “ip route add” and before my first reset I was able to get ping to send ARP requests out of the box via “ping –I eth8 192.168.22.30” type command lines. After the reset I don’t seem to be able to get out of the box on the quad cards.

My various route attempts created a big mess with no visible improvement in my situation. Thus, I think it is counter productive to list them here.

At this point I am hitting a brick wall on several issues:
1) Why do runs that seem like they should be the same produce different results?
2) Can I go from one port on a quad card to another port on a quad card? I am willing to do “crazy things” like assign a different network number (192.168.21.x, 192.168.22.x, etc.) to each port if necessary.
3) How do I set up whatever is needed to use Perl to go from a quad port on one Linux box to a quad port on another Linux box?
4) Why, when I was getting ARP requests out of the box was I not getting any ARP replies (I used Ethereal on both ends of the connection)

Thank you,
Bruce

Edit: g0n - code tags and formatting

Replies are listed 'Best First'.
Re: socket communication problems
by liverpole (Monsignor) on Jan 31, 2007 at 23:01 UTC
    Hi Bruce32903,

    One thing I see right off the bat is that you're using my $MySocket within some of the if ... else clauses.  That means that they are different variables from the $MySocket at the top of the program.

    Here's a simplified example:

    #!/usr/bin/perl use strict; use warnings; my $MySocket = "abc"; if (1) { my $MySocket = "123"; print "Inside while loop: \$MySocket = '$MySocket'\n"; } print "Outside while loop: \$MySocket = '$MySocket'\n"; __END__ Output: Inside while loop: $MySocket = '123' Outside while loop: $MySocket = 'abc'

    When you remove the extra my keywords, does that get you closer to success?


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
      Oops, block copy got me again.  I have looked at the code 
      dozens of times and not seen the extra "my".  Thank you.
      After this fix the "A direction" and "B direction" give the
      same results.  That is a step in the right direction.  The
      alarm works and I am not getting stuck (good) but I am still
      not getting out of the box (bad).  I assume that I have a
      routing issue.  My next step is to address the "double new"
      issue in the next comment.  Then I will see how far I have
      gotten.
      
      Thank you,
      Bruce
      
      
Re: socket communication problems
by chromatic (Archbishop) on Feb 01, 2007 at 01:01 UTC

    I've seen this code before somewhere:

        $MySocket=new IO::Socket::INET->new(Proto => 'udp',

    It's broken because there's an extra new call in there, which almost definitely isn't what you want. Where did you find this code? I'd like to fix the source, if possible.

      Google Code Search finds "about 50" instances of it in the stuff it indexes. Might even could track down Patient Zero through that if you're really bothered by it. :)

      I need to look around my desk at home to try to determine
      where I got the extra "new" from.  I have been using Lincoln
      Stein's Perl networking book (examples probably correct), 
      the Perl Cookbook and many Google examples.  My guess is that
      I got it from a Google example.
      
      Inside the if blocks I changed the "new" lines to look like:
      $MySocket = IO::Socket::INET->new(Proto => 'udp',
      
      After correcting the "new" issue I APPEAR to fail to 
      operate in what seems to be the exact same way.  From the 
      command line the send statements whip by quickly.  The recv
      statements pause for the length of alarm time and repeat 
      for several retries.  This is exactly what I currently 
      expect to see on the command line.  But, I am not seeing 
      any activity on the hub (quad card only) LEDs.
      
      Looking at this in a little more detail I used Ethereal 
      (now WireShark) on the machine that has the quad port cards.
      
      ARGUMENT A
      Packets from 192.168.22.30 to 192.168.21.28
      No packets were seen on eth10 (the sending end)
      
      ARGUMENT B
      Packets from 192.168.21.28 to 192.168.22.30
      No packets were seen on eth8 (then sending end)
      
      ARGUMENT C
      Packets from 192.168.21.28 to 192.168.20.223 (NOT quad card)
      No packets were seen on eth8 (I hoped this was the sending end)
      4 UDP packets were captured on eth0 (part of the .20 net)
      
      THUS:
      
      1) I think I can send from box to box with the "my" and 
      "new" fixes.  Thank you for the good suggestions.  With this
      I should be able to work on my required final goal.
      
      2) I do not seem to be able to get out of the box when I 
      try to go from one port to another port on quad cards in the 
      same box.  I was told to expect this.  Is there a way around 
      this?  Can I use a different net for each port of the quad
      cards to prevent "route" from taking the unnecessary 
      segments out of the transmission?  This would be helpful for 
      single machine code development and other test projects 
      down the road.
      
      3) My "argument C" example shows "route" changing my ports
      for me.  The packet went out the port that makes good sense, 
      not the port I coded.  At times it would be handy if I could
      overpower this "feature" of good routing.
      
      Thank you for the help.  I can proceed now.  If there are 
      any suggestions on how I can force my routes (items 2 & 3) 
      I would appreciate additional information.
      
      Thanks,
      Bruce