http://www.perlmonks.org?node_id=1059894

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

Hi,

I have implemented socket code using tcp protocol.

client is running on windows machine.

Problem: when i am sending 'sh' command then server terminates

client code:

#!perl -w use strict; use IO::Socket::INET; # auto-flush on socket $| = 1; # create a connecting socket my $socket = new IO::Socket::INET ( PeerPort => '7775', PeerHost => '127.0.0.1', Proto => 'tcp', ); die "cannot connect to the server $!\n" unless $socket; print "connected to the server\n"; my $command_to_send = "sh"; $socket->send($command_to_send); #my $size = $socket->send($req); #print "sent data of length $size\n"; # notify server that request has been sent shutdown($socket, 1); while (1) { my $recieved_data= <$socket>; if ( defined $recieved_data ) { chomp($recieved_data); print "recieved_data=======>$recieved_data\n"; if ( $recieved_data =~ m/^done/i ) { print "========>done\n"; exit 0; #return 0; } } } $socket->close();

server is running on solaris box

Server code:

#!/usr/bin/perl -w use strict; use IO::Socket::INET; my $PORT = $ARGV[0]; my $IP_ADDRESS = $ARGV[1]; if ((!defined $PORT) || (!defined $IP_ADDRESS)){ print "Please provide the IP-Adress or Port no!!\ne.g. Perl TCP_Server +.pl <port no> <IP-Address>\nPerl TCP_Server.pl 7777 127.0.0.1\n"; exit 0; } my $Receiving_Port = $PORT; # flush after every write $| = 1; my ( $socket, $received_data ); my ( $peeraddress, $peerport ); $socket = new IO::Socket::INET ( LocalHost => $IP_ADDRESS, LocalPort => $Receiving_Port, Proto => 'tcp', Listen => 5, Reuse => 1 ) or die "ERROR in Socket Creation : $!\n"; $socket->listen(); $socket->autoflush(1); print "TCP Server Started\n"; # Stay in endless loop to wait and look for tcp commands to be execute +d. my $addr; while (1) { $addr = $socket->accept(); print "$addr\n"; $peeraddress = $addr->peerhost(); $peerport = $addr->peerport() ; my $pid = fork(); # ignore signal CHILD in linux to prevent Zombie Process. if ( $^O !~ m/mswin32/i ) { $SIG{CHLD} = 'IGNORE'; } if ( $pid == 0 ) { my $exitCode; while (<$addr>) { # Read all messages from client # Print received message $received_data = $_; # Execute RunCommand for running the command and sending i +ts response back. $exitCode = RunCommand( $received_data, $peeraddress, $pee +rport ); } exit $exitCode; close $addr; } } # Close socket when Command is received. $socket->close(); sub RunCommand { my $Command_To_Send = shift; my $send_ip = shift; my $peerport = shift; # file handler which will have response values. my $fileHandler; print "Executing: '$Command_To_Send'\n"; print "Output on: '$send_ip:$peerport'\n"; if ( $Command_To_Send =~ m/Check Connectivity/i ) { #sleep 20; ## Send Response back to Client, that tcp_server is now connec +ted. print $addr "Connected to TCP socket server\n"; return 0; } if ( $Command_To_Send =~ m/\x03|\x1A/i ) { return 0; } # Execute the command by opening a pipe to channel. -| will read S +TDOUT # and assign it to fileHandler. my @pid = open( $fileHandler, '-|', "$Command_To_Send 2>&1" ); if ( $^O !~ m/mswin32/i ) { #Traversing pid array. foreach (@pid) { print "'$Command_To_Send' PID: $_\n"; print $addr "Process ID = $_\n"; } } # if no pid is assigned, means the command was incorrect or error +while # sending the commmand. if ( $#pid == -1 ) { warn "Cannot Open Command !!\n"; print $addr "'$Command_To_Send' Unable to Start\n"; } # hotlist the filehandler for immediate flushing, no buffering. my $ofh = select $fileHandler; $| = 1; select $ofh; print $addr "Sending Command '$Command_To_Send'\n"; # write response of command to tcp socket which is sent to ATF. while (<$fileHandler>) { print $addr $_; } print $addr "\n"; print $addr "normal-exit\n"; print $addr "done\n"; # Killing if any process has not completed gracefully. # Traversing pid array. foreach (@pid) { my $curr_pid = $_; if ( $^O !~ m/mswin32/i ) { kill 9, $curr_pid; } } #Closing filehandler. close($fileHandler); return 0; }

please help me to resolve this issue
Thanks in advnace

Replies are listed 'Best First'.
Re: TCP Client not working
by oiskuu (Hermit) on Oct 27, 2013 at 17:45 UTC

    If your intent is to start an interactive shell on the server, then you'll probably want to spawn it with a TTY (using IO::Pty).

    my $pty = new IO::Pty; $pty->set_raw(); my $pid = fork // die; unless ($pid) { $pty->make_slave_controlling_terminal(); close STDIN; open STDIN, "+>&", $pty->slave; # ditto for STDOUT, ...; close $pty->slave; exit !exec @the_program; } close $pty->slave; event_loop_passing_data_between($pty, $socket)
    To pass window size/ttype/etc., the Net::Telnet interface might be chosen. You've essentially reimplemented the telnetd.

    OTOH, if you simply want to avoid signals from the child interrupting the server process, the following might be of use:

    use POSIX; my $pid = fork(); if ( $pid == 0 ) { setsid(); close STDIN; close STDOUT; close STDERR; RunCommand( ... ); }
    Child setsid() detaches it from the controlling tty.