I'm trying to create a small TCP server with perl. I have a small Java app on my blackberry that sends data to the server. It's simple data, just an IP address, a colon, then a number. The server then takes that information, looks up a switch's actual port name (i.e. FastEthernet0/2) from a hash, and SSH's to a switch and applies some commands for me.
I've gotten the basic functionality to work. If a connection comes in and calls a port that's not defined in the hash, it returns an error. If a connection comes in that is not formatted properly, it ignores it. If a connection comes in that is formatted correctly, it connects and enters the commands.
The problem is that when a good connection comes in, the script works its SSH magic and then crashes with the following error Can't call method "recv" on an undefined value at udplisten802.pl line 44 (Yes, the script is called UDPlisten when I'm using TCP. I started out trying to use UDP but found out i couldn't tunnel UDP through my BES server, so i switched it and never renamed :) )
It only has issues if it has to SSH to the device. I put some print statements in to see where it gets before it dies. It seems its going back as far as it needs to, but when the code reads $client=$sock->accept();, it doesn't seem to actual let the socket acccept the connection. I've tried putting in a 2nd $client=$socket->accept(); right after the first, but that made it so that it only reacted to every other connection I made.
I've quite confused why it's not behaving. If someone could take a look, it'd be greatly appreciated. I will post the script as well as another script I made for generating test traffic. Please go easy on me, I'm a fairly novice Perl guy, but I'm trying to learn. Thanks!!
udplisten.pl - the actual "Server" script.
use IO::Socket; use Net::Appliance::Session; use strict; use warnings; my ($sock,$LOCALPORT,$MAXLEN,$newmsg,$USER,$PASSWORD,$FILENAME,%PORTHA +SH,$client,$message); $LOCALPORT=2500; $MAXLEN=5151; $USER="REMOVED"; $PASSWORD="REMOVED"; $FILENAME="ports.txt"; #Pull in port mappings. Format is <Patch Panel> , <Switch Port name> I +.E. 13,FastEthernet1/0/20 print "Opening Ports and Reading\n"; open PORTS, $FILENAME or die $!; my @ports=<PORTS>; close PORTS; foreach(@ports) { chomp($_); my @t=split(/,/,$_); $PORTHASH{$t[0]}=$t[1]; } print "Port reading complete\n"; #Open a file to print things to (implemented later on), reusing the sa +me variable. $FILENAME=">data.txt"; #open STDOUT, '>>data.txt' or die $!; #Open Listener on TCP 2500 #$sock= IO::Socket::INET->new(LocalPort => $LOCALPORT,Proto => 'udp') +or die "Socket: $@"; $sock= IO::Socket::INET->new(LocalPort => $LOCALPORT,Proto => 'tcp', R +euse => 1, Listen => SOMAXCONN) or die "Socket: $@"; print "Starting... running on port: $LOCALPORT\n"; while(1) { $client=""; $client = $sock->accept(); $client->recv($message,1024); print "Here AGAIN!6\n"; while (1) { print "In here:\n"; print $message."\n"; #If the packet has the right format of <Switch IP> : <Patch pa +nel mapping>, SSH to it and implement the macro stored on the switch + if ($message=~ /(.*)\:(\d*)/) { #Make sure the port mapping exists, If it does, connect SS +H session my $host=$1; my $portnumber=$2; if (exists $PORTHASH{$portnumber}) { print "Exists!\n"; doSSH($host,$PORTHASH{$portnumber}); print "Here AGAIN!5\n"; last; }else { print"Port: ".$portnumber." is not defined. Host: ".$h +ost.".\n"; $client->send('Not Defined!!'); last; print "Here AGAIN!3\n"; } } else { last; close $client; } last; } } #Clean up sub doSSH { my $host=$_[0]; my $interface=$_[1]; my $s = Net::Appliance::Session->new($host); eval { $s->do_paging(0); $s->do_privileged_mode(0); #Send all SSH output to STDOUT so i can watch it $s->input_log(*STDOUT); print "Connecting to $host\n"; $s->connect(Name => $USER, Password =>$PASSWORD); $s->begin_configure(); $s->cmd("interface ".$interface." "); $s->cmd("macro apply 8021x"); $s->end_configure(); $s->close; }; if ( UNIVERSAL::isa($@,'Net::Appliance::Session::Exception') ) { print $@->message, "\n"; # fault description from Net::Applia +nce::Session print $@->errmsg, "\n"; # message from Net::Telnet print $@->lastline, "\n"; # last line of output from your appl +iance # perform any other cleanup as necessary $client->send('FAILED--'); }else { $client->send('Successful'); } print "Here AGAIN!4\n"; }
Simplesend.pl - just loops forever sending test traffic every 10 seconds.
use IO::Socket; use strict; my $LOCALPORT=2000; my ($newmsg,$MAXLEN,$TIMEOUT); $MAXLEN=5151; $TIMEOUT=5; while (1) { my $counter=10; while ($counter>0) { print "Sending in: ".$counter."\n"; $counter--; sleep 1; } print "Sending!\n\n"; my $sock= IO::Socket::INET->new(Proto => 'tcp', PeerPort=>'2500', +PeerAddr=>'192.168.110.253') or warn "Socket: $@\n"; if ($sock) { print $sock "192.168.250.13:13"; close ($sock); } }
One more piece of info, if anyone wants to run the script to test with actual data, the "ports.txt" file is formatted like this: <number>,<portanme> One per line. I.E. 13,FastEthernet0/2
In reply to TCP Server Exits Loop and Crashes with error by rojmab
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |