Single command to and from client/server

J

Just in

List,

From the TCP client with IO::Socket on the perlipc page I have made the
following (apologies for the formatting):

# Server code

use strict;

use warnings;

use IO::Socket;

use Net::hostent;

use Sys::Hostname 'hostname';

$|++;

my $Port = 1971;

my $Host = hostname();

my $Server = IO::Socket::INET->new(Proto => 'tcp', LocalPort => $Port,
Listen => SOMAXCONN, Reuse => 1);

die "Can't setup Server" unless $Server;

print "[Server $Host accepting Clients]\n";

while(my $Client = $Server->accept())

{

$Client->autoflush(1);

print $Client "Connected to $Host\n";

my $HostInfo = gethostbyaddr($Client->peeraddr);

printf "[Connect from %s]\n", $HostInfo->name || $Client->peerhost;

while(<$Client>)

{

print $Client `$_` if /^dir/i;

print $_;

last;

}

close $Client;

}

######################################################################

# Client code

#!/usr/local/bin/nsPerl5.005_03/nsperl -w

use strict;

use IO::Socket;

my ($KidPID, $Line);

my $Port = '1971';

my $Host = '123.123.123.123';

my $Handle = IO::Socket::INET->new(Proto => 'tcp', PeerAddr => $Host,
PeerPort => $Port) or die "Cant connect to $Host on $Port:- $!";

$Handle->autoflush(1);

die "Cant fork: $!" unless defined($KidPID = fork());

if($KidPID)

{

while(defined($Line = <$Handle>))

{

print STDOUT $Line;

}

kill("TERM", $KidPID);

}

else

{

print $Handle 'dir d:';

#while(defined($Line = <STDIN>))

#{

# print $Handle $Line;

#}

}

I can get connectivity between the two machines, and with the while
uncommented on the client I can key in "dir d:" and a get a response from
the server.

However what I really need is code that fires off a command from the client
with arguments (without keying it in from STDIN), which can then be picked
up by the server, processed and then returned to the client, closing the
client/connection after the return of data, rather than the continuous
interactive example that I borrowed this code from.

I guess the else in my client is the show stopper because my xterm just sits
there. And when I control C the xterm client the server flushes out the "dir
d:" string to the terminal. So I further guess that I need to close/kill one
of the processes that fork spawns in order for it to return, but I'm not
sure how.

Any help appreciated, thanks.

Just in

P.S./ The client sits on a Solaris machine (Perl 5.5 binary dist), while my
server is on Win2003 server (AS 5.6).
 
R

Rocco Caputo

List,

From the TCP client with IO::Socket on the perlipc page I have made the
following (apologies for the formatting):

[... AIEEE! ...]
######################################################################

# Client code

#!/usr/local/bin/nsPerl5.005_03/nsperl -w

use strict;

use IO::Socket;

my ($KidPID, $Line);

my $Port = '1971';

my $Host = '123.123.123.123';

my $Handle = IO::Socket::INET->new(Proto => 'tcp', PeerAddr => $Host,
PeerPort => $Port) or die "Cant connect to $Host on $Port:- $!";

$Handle->autoflush(1);

die "Cant fork: $!" unless defined($KidPID = fork());

if($KidPID)

{

while(defined($Line = <$Handle>))

{

print STDOUT $Line;

}

kill("TERM", $KidPID);

}

else

{

print $Handle 'dir d:';

#while(defined($Line = <STDIN>))

#{

# print $Handle $Line;

#}

}

I can get connectivity between the two machines, and with the while
uncommented on the client I can key in "dir d:" and a get a response from
the server.

However what I really need is code that fires off a command from the client
with arguments (without keying it in from STDIN), which can then be picked
up by the server, processed and then returned to the client, closing the
client/connection after the return of data, rather than the continuous
interactive example that I borrowed this code from.

Just to be fair, I should let you know that I've changed your code
without testing it.

# Server code
use strict;
use warnings;
use IO::Socket;
use Net::hostent;
use Sys::Hostname 'hostname';

$|++;

my $Port = 1971;
my $Host = hostname();

my $Server = IO::Socket::INET->new(
Proto => 'tcp', LocalPort => $Port, Listen => SOMAXCONN, Reuse => 1
);

die "Can't setup Server" unless $Server;

print "[Server $Host accepting Clients]\n";

Everything above is pretty much the same. Here you accept new sockets
and run a single command from each. When the command's done, you close
the client and accept another connection.

Yes, it's single-tasking. That is, it can only execute one client's
command at a time. If you want multitasking, try
http://poe.perl.org/?POE_Cookbook/Job_Server or something.

while(my $Client = $Server->accept())
{
$Client->autoflush(1);
print $Client "Connected to $Host\n";
my $HostInfo = gethostbyaddr($Client->peeraddr);
printf "[Connect from %s]\n", $HostInfo->name || $Client->peerhost;

Fetch the command, and remove the newline from it.

my $cmd = <$Client>;
chomp $cmd;

Respond with the results, if it's a valid command. Close the socket
afterwards, disconnecting the client. You did say you wanted to execute
one command noninteractively.

print $Client `$cmd` if /^dir/i;
print $cmd;
close $Client;
}

On the client side, I've put the #! line before the comment. You
probably already had it that way but added the "Client code" comment for
your posting.

By the way, you should really REALLY really REALLY really consider
upgrading Perl. 5.8.2 is years newer than 5.005_03.

#!/usr/local/bin/nsPerl5.005_03/nsperl -w
# Client code

use strict;
use IO::Socket;

my $Port = '1971';
my $Host = '123.123.123.123';

my $Handle = IO::Socket::INET->new(
Proto => 'tcp', PeerAddr => $Host, PeerPort => $Port
) or die "Cant connect to $Host on $Port:- $!";
$Handle->autoflush(1);

print $Handle "dir d:\n";

while(defined($Line = <STDIN>))
{
print $Handle $Line;
}

That non-interactively sends a directory command, reads everything sent
back by the server, and exits when the server closes the connection. No
forking or STDIN are necessary.
 
J

Just in

Rocco,

Thanks, but it doesnt work : (
The client just sits there, but if you hit enter on the client the server
replies on its terminal (because of strict and warnings being on) that $cmd
isnt initialised (even when you type in dir d: <enter>)

------8<---------------
Yes, it's single-tasking. That is, it can only execute one client's
command at a time. If you want multitasking, try
http://poe.perl.org/?POE_Cookbook/Job_Server or something.

------8<---------------
Single tasking will be fine for now - the command runs in within a split
second.

------8<---------------
while(my $Client = $Server->accept())
{
$Client->autoflush(1);
print $Client "Connected to $Host\n";
------8<---------------
Unfortunately "Connected to $Host" goes to the server terminal rather than
my client. I dont really need this, so it doesnt really matter.

------8<---------------
Respond with the results, if it's a valid command. Close the socket
afterwards, disconnecting the client. You did say you wanted to execute
one command noninteractively.

------8<---------------
Yeah, but I cant even get a dir listing, and nothing goes to my client

------8<---------------
On the client side, I've put the #! line before the comment. You
probably already had it that way but added the "Client code" comment for
your posting.

------8<---------------
Yup, youre right.

------8<---------------
By the way, you should really REALLY really REALLY really consider
upgrading Perl. 5.8.2 is years newer than 5.005_03.

------8<---------------
No can do, IT own the setup, I'm just an engineer.

------8<---------------
#!/usr/local/bin/nsPerl5.005_03/nsperl -w
# Client code
------8<---------------
print $Handle "dir d:\n";

while(defined($Line = <STDIN>))
{
print $Handle $Line;
}

------8<---------------
Since it doesnt work and not being sure why you put STDIN in there, I tried
changing it to <$Handle> but to no avail. Is it correct?

------8<---------------
That non-interactively sends a directory command, reads everything sent
back by the server, and exits when the server closes the connection. No
forking or STDIN are necessary.

------8<---------------
Hmm, see above.

Hope you can still help out to get this running.

Just in
 
J

Just in

---------8<----------
Just in said:
Rocco,

Thanks, but it doesnt work : (
The client just sits there, but if you hit enter on the client the server
replies on its terminal (because of strict and warnings being on) that $cmd
isnt initialised (even when you type in dir d: <enter>)
---------8<----------

Ignore the above. I fiddled around a bit longer and got it going. The
difference being that I had to put the fork back in, and put a \n after the
"dir d:" - Thats another thing, the single quotes werent helping because
they werent interpreting. Server code remains as what perlipc had it.

Thanks man,

Just in
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top