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

Hi Monkers!!!

I am struggling while converting a perl program into CGI script. Actually,I have to pass data IP address to a Server program running in MS/Win box.When I am trying to run via CGI, the socket is not getting created

#!/usr/bin/perl use IO::Socket; $destination = 'xxx.xxx.xxx.xxx'; $sock = new IO::Socket::INET (PeerAddr => 'xxx.xxx.xxx.xxx', PeerPort => 4444, Proto => 'tcp', ); die "Socket could not be created. Reason: $!\n" unless $sock; print $sock "ping:$destination \n"; print "Client Connected. \n"; print "Server says: ",scalar(<$sock>); print $sock "Message acknowledged from the client!\n"; print $sock "Good Bye! \n"; print "Ping result =>: ",scalar(<$sock>); close ($sock);

One more query what is the mechanism of doing $getdata = 'nslookup www.perlmonks.com'; (as in Linux)?

cheers!

Rock

20060713 Janitored by Corion: Added code tags, as per Writeup Formatting Tips

Replies are listed 'Best First'.
Re: Convering Perl socket program into CGI.
by McDarren (Abbot) on Jul 13, 2006 at 11:18 UTC
    Just to address your second question:
    "One more query what is the mechanism of doing $getdata = 'nslookup www.perlmonks.com'; (as in Linux)?"

    There are several ways to approach this:

    1. You could use backticks (not really recommended as it is platform-specific):
      my $getdata = `/usr/bin/nslookup www.perlmonks.com`;
    2. You could use the built-in system1 function (also not particulary recommended):
      my $getdata = system("/usr/bin/nslookup www.perlmonks.com");
    3. Possibly the best option is to use another built-in function, gethostbyname2
      use Socket; my $ip = gethostbyname("www.perlmonks.com");
    4. One further option is the Net::Nslookup module. I've not used this one, so I can't really comment on it (although it does look quite simple).

    1. There are all sorts of traps for the unwary with system, refer to the docs for more info.

    2. gethostbyname when called in list context will return additional information - again, refer to the docs.

    Hope this helps,
    Darren :)

Re: Convering Perl socket program into CGI.
by kabeldag (Hermit) on Jul 13, 2006 at 13:01 UTC
    Well first things first. You have gotto have access to the IO::Socket module. Check the contents of @INC;

    Does the socket server binding/init die or not ?

    Is that the complete CGI script that you have posted ? Or do you need to convert that code to CGI ?
    That code doesn't look like a CGI ready script.
      You are correct. I have to convert it into CGI. There lies the problem
      cheers Rock

      Edited by planetscape - moved content out of signature (readability)

Re: Convering Perl socket program into CGI.
by sgifford (Prior) on Jul 13, 2006 at 16:35 UTC
    What's happening when you run this? Do you get an error in the log, and if so what is it?
      The posted code runs just fine. It passes the IP address to Server and receives the message, from command line . Problem is when I convert it to cgi, socket is not getting created, nor I get message that it is not getting created. I am pasting part of the cgi script I am trying to make. And yes I am beginner in CGI scripting.

      print "<p class=\"systemMsg\">LINE AFTER SOCKET CREATION".$sock."</p>\n";

      The web page shows till this line, but again $sock value is not getting printed. Hence I conclude that script has problem in creating socket. For more info, I am pasting my server script as well.

      #!/usr/bin/perl #Client Script use IO::Socket; #domain name suffix - if we need it $domainName=""; $nodeName = ""; if (! $FORM{"\$selected_rows.Node"}) { print "<p class=\"systemMsg\">No Node Specified.</p></body></h +tml>"; die; } else { $nodeName = $FORM{"\$selected_rows.Node"}.$domainName; print "<p class=\"systemMsg\">Pinging host ".$nodeName."</p>\n +"; } $sock = new IO::Socket::INET (PeerAddr => '172.30.166.234', PeerPort => 23 , Proto => 'tcp', ); print "<p class=\"systemMsg\">LINE AFTER SOCKET CREATION".$sock."</p>\ +n"; die "Socket could not be created. Reason: $!\n" unless $sock; print "<p class=\"systemMsg\">Socket could not be created. Reason: $!\ +n".$sock."</p>\n"; print $sock "ping:".$nodeName."\n"; print "Client Connected. \n"; print "Server says: ",scalar(<$sock>); print $sock "Message acknowledged from the client!\n"; print $sock "Good Bye from client! \n";
      #!/usr/bin/perl #Server Script use warnings; use strict; use IO::Socket; use IO::Select; use Net::Ping; my $serverport = 23; # create a socket to listen on SOMAXCONN = 512 my $server = new IO::Socket( Domain => PF_INET, Proto => 'tcp', LocalPort => $serverport, Listen => SOMAXCONN, ); die "Cannot bind: $!\n" unless $server; # create a 'select' object and add server fh to it my $selector = new IO::Select($server); # stop closing connections from aborting the server $SIG{PIPE} = 'IGNORE'; # loop and handle connections print "Multiplex server started on port $serverport...\n"; while (my @clients = $selector->can_read) { # input has arrived, find out which handles(s) foreach my $client (@clients) { if ($client == $server) { # it's a new connection, accept it my $newclient = $server->accept; my $port = $newclient->peerport; syswrite $newclient, "You've reached the server port at # $por +t\n"; #my $port = $newclient->peerport; my $name = $newclient->peerhost; #print "New client $port:$name\n"; $selector->add($newclient); } else { # it's a message from an existing client my $port = $client->peerport; my $name = $client->peerhost; my ($message, $buf, $host); my $newclient = $client->accept; # my $port = $newclient->peerport; my $reach = Net::Ping->new($ > ? "tcp": "icmp"); (defined $reach) or die "Couldn't create Net::Ping object: $!\n"; if (sysread $client, $message, 1024) { print "\n Client $name:$port sent: $message\n"; #while($newserver = $newserver->accept()) #{ while (defined ($buf = <"$message">)) { print "Buffer: $buf"; $host = (split(/:/,$buf))[1]; print "Host: $host"; print "Remote IP to be pinged $host"; if($reach->ping("$host")){ # print "$host is reachable"; syswrite $client, "reachable +$host "; } else{ # print "$host is unreachable"; syswrite $client, "unreachab +le $host"; } } # }#end of outer while {} syswrite $client, "\n Message received OK\n"; } else { $selector->remove($client); $client->shutdown(SHUT_RDWR); print "\nClient disconnected\n"; # port, name not defined } } } }#end of foreach loop
      cheers Rock

      Edited by planetscape - added code tags; moved content out of signature (readability)

      I don't get any error cause of that die statement, but when I try to print the value of $sock, it remains blank.
      cheers Rock

      Edited by planetscape - moved content out of signature (readability)

Re: Convering Perl socket program into CGI.
by kabeldag (Hermit) on Jul 14, 2006 at 08:49 UTC
    Ok. Well here is something that is near what I assume you are looking for.
    Except, it doesn't branch on a QUERY_STRING, and of course I am not using CGI.pm.

    If you so need to do that. Then you may like to branch your code via something from $ENV{QUERY_STRING}. Or even better, use CGI.pm. And have branching from something like this :
    use CGI qw/:standard/; my $cgiObj = new CGI; my $addr_to_ping=$cgiObj->param('ip_address');
    The url with the CGI param would look something like this : http://some-site.net/client.pl?ip_address=66.39.54.27

    Client/CGI script/Ping output (to a Web browser) This works for me.
    #!/usr/bin/perl #Client Script use strict; use IO::Socket; print "Content-type:text/html\n\n"; my $server="192.168.0.101"; my $server_port=23; my $nodeName = "192.168.0.101"; my $sock = new IO::Socket::INET (PeerAddr =>$server, PeerPort => $server_port , Proto => 'tcp', ) or do_exit("Couldn't connect to $server +:$server_port.\n"); print $sock "ping:$nodeName\n"; while(my $server_response=(<$sock>)) { chomp($server_response); print "Server said: $server_response<BR>" if($server_response); if($server_response eq "MOK") { exit(0); } } sub do_exit { my $err_msg=$_[0]; print "$err_msg"; exit(1); }
    Server/pinger
    #!/usr/bin/perl #Server Script use warnings; use strict; use IO::Socket; use IO::Select; use Net::Ping; my $serverport = 23; # create a socket to listen on SOMAXCONN = 512 my $server = new IO::Socket( Domain => PF_INET, Proto => 'tcp', LocalPort => $serverport, Listen => SOMAXCONN, ); die "Cannot bind: $!\n" unless $server; # create a 'select' object and add server fh to it my $selector = new IO::Select($server); # stop closing connections from aborting the server $SIG{PIPE} = 'IGNORE'; # loop and handle connections print "Multiplex server started on port $serverport...\n"; while (my @clients = $selector->can_read) { # input has arrived, find out which handles(s) foreach my $client (@clients) { if ($client == $server) { # it's a new connection, accept it my $newclient = $server->accept; my $port = $newclient->peerport; syswrite $newclient, "Welcome!\n"; my $name = $newclient->peerhost; $selector->add($newclient); }else{ # it's a message from an existing client my $port = $client->peerport; my $name = $client->peerhost; my ($message, $buf, $host); my $newclient = $client->accept; my $reach = Net::Ping->new($ > ? "tcp": "icmp"); (defined $reach) or die "Couldn't create Net::Ping object: $!\ +n"; if (sysread $client, $message, 1024) { print "Client $name:$port sent: $message"; while (defined ($buf = <"$message">)) { $host = (split(/:/,$buf))[1]; chomp($host); print "Remote IP to be pinged $host\n"; if($reach->ping("$host")) { print "$host is reachable\n"; print $client "reachable $host\n"; }else{ print "$host is unreachable\n"; print $client "unreachable $host\n"; } } print $client "\n Message received OK\n"; }else{ $selector->remove($client); $client->shutdown(SHUT_RDWR); print "\nClient disconnected\n"; # port, name not defined } } } }

      Why are you using the weird globbing construct:

      while (defined ($buf = <"$message">)) {

      Granted, it could act as a cool filter for weird hostnames that likely won't respond to pings, but I think this should be explained...

      I really appreciate the effort, but when I run the client as it is, it waits for indefinite amount of time. From server I can make out that it is really connected, but nothing happens after that. I expected that it should give some message in a web page
      cheers Rock