Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

socket help

by Anonymous Monk
on Feb 14, 2011 at 00:22 UTC ( [id://887907]=perlquestion: print w/replies, xml ) Need Help??

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

i have a client/server tcp socket script that works but i would like to send stdout from server back to client. for example i send ls /tmp to server i would like to see the ls output on the client. any help would be great

Client code:

#!/usr/bin/env perl use IO::Socket; use strict; my $socket = new IO::Socket::INET ( PeerAddr => $_, PeerPort => '7071', Proto => 'tcp', ); die "Coudn't open socket" unless $socket; $socket->autoflush(1); my $dir = "/tmp"; print $socket "ls:$dir\n"; close($socket);

server code:

#!/usr/bin/env perl # perl modules use IO::Socket; use POSIX qw(:sys_wait_h); use Sys::Hostname; my $hostname = hostname; my $port = "7071"; $SIG{CHLD} = 'IGNORE'; # make socket connection my $socket = new IO::Socket::INET ( LocalHost => "$hostname", LocalPort => "$port", Proto => 'tcp', Reuse => 1, Listen => SOMAXCONN, ); die "Could not create socket: $!\n" unless $socket; while ($client = $socket->accept()) { $client->autoflush(1); while (<$client>) { chomp; my ($command,@var2) = split(":", $_); my $cmd; $pid = fork; if ($pid == 0){ } else { `kill $pid 2>/dev/null`; } unless ( $pid ){ if ($command eq 'ls'){ $cmd = sprintf("ls -s @var"); } $run_cmd = system($cmd); } } close($client); } close($socket);

Replies are listed 'Best First'.
Re: socket help
by ikegami (Patriarch) on Feb 14, 2011 at 02:44 UTC
    use IPC::Open3 qw( open3 ); while (my $client = $socket->accept()) { while (<$client>) { chomp; my ($cmd, @args) = split(/:/, $_); my @cmd; if ($cmd eq 'ls') { @cmd = ( 'ls', '-s', '--', @args ); } if (@cmd) { open(local *C_STDIN, '<', '/dev/null') or die; open(local *C_STDOUT, '>&, $client) or die; my $pid = open3('<C_STDIN', '>C_STDOUT', '>C_STDOUT', @cmd); waitpid($pid, 0); } } }
      I tried the suggestion and still got nothing back.
      client code:
      #!/usr/bin/env perl use IO::Socket; $remote_port=7071; $remote_host="localhost "; $socket = IO::Socket::INET->new(PeerAddr => $remote_host, PeerPort => $remote_port, Proto => "tcp", Type => SOCK_STREAM) or die "Couldn't connect to $remote_host:$remote_port : $@\n"; $socket->autoflush(1); # ... do something with the socket print $socket "ls:/tmp\n"; while (<$socket>) { print "$_\n"; } # and terminate the connection when we're done close($socket);

      Server code:
      #!/usr/bin/env perl # perl modules use IO::Socket; use POSIX qw(:sys_wait_h); use Sys::Hostname; use IPC::Open3 qw( open3 ); # get hostname my $hostname = hostname; # Port my $port = "7071"; $SIG{CHLD} = 'IGNORE'; # make socket connection my $socket = new IO::Socket::INET ( LocalHost => "$hostname", LocalPort => "$port", Proto => 'tcp', Reuse => 1, Listen => SOMAXCONN, ); die "Could not create socket: $!\n" unless $socket; # allow server to accept clients while ($client = $socket->accept()) { # flush input $client->autoflush(1); # input from client while (<$client>) { chomp; # read command and put rest in array my ($command,@var2) = split(":", $_); my $cmd; if ($command eq 'ls'){ @cmd = ( 'ls', '-s', '--', @var2 ); } # run command if (@cmd) { open(local *C_STDIN, '<', '/dev/null') + or die; open(local *C_STDIN, '>&', $client) or + die; my $pid = open3('C_STDIN', '>C_STDOUT' +, 'C_STDOUT', @cmd); waitpid($pid, 0); } } # close client close($client); } # close socket so it can reused close($socket);
        That's not the code I posted at all, and you're hiding potential error messages by not using use strict; use warnings;.
Re: socket help
by snoopy (Curate) on Feb 14, 2011 at 02:30 UTC
    The implicit use of global $_ in the client code seems a bit odd. This variable is not set explicitly from the command line without careful invocation:
    echo myarg | perl -nle 'print "ARG=<$_>\n"' ARG=<myarg>

    You're better off, at least, fetching from ARGV:

    my ($hostname) = @ARGV; die "usage: $0 hostname" unless $hostname; my $socket = new IO::Socket::INET ( PeerAddr => $hostname, PeerPort => '7071', Proto => 'tcp', );
    ...or however you want to parse the command line arguments in @ARGV.
      $_ is supposed to be $ARGV[0].
      PeerAddr => $ARGV[0],
      I've also tried using backticks
      chomp(my $output = `ls /tmp 2>&1`);
      It's like the client isn't waiting for the server to finish
Re: socket help
by Anonymous Monk on Feb 14, 2011 at 00:44 UTC
    use backticks/qx instead of system to capture the output of ls, then print it back to the client
      i've tried using backticks and still get nothing. I also just tried sending the output from the server to a file and having the client read the file. This would work as long as the client didn't have to wait for the server. The client would not wait for the server to finish before it read the file.
        i've tried using backticks and still get nothing.

        Show what you tried

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://887907]
Approved by broomduster
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (5)
As of 2024-04-19 13:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found