tags:

views:

512

answers:

1

So far I have written a Perl server that runs constantly in the background, when it receives inbound connections a process is forked and that then handles that one connection. What I ultimately want it to be able to do is accept inbound php connections through the socket of course run these commands and then relay and information back. So far I have managed to get this working 100% with a Perl scripted client but it doesn't work 100% with a php one.

[Instead of pasting the hole wall of text here is the actual send and receive section.]

print "Binding to port ...\n";
$server = IO::Socket::INET->new(
            Listen => 1, 
            LocalAddr => $_server, 
            LocalPort => $_port, 
            Proto => 'tcp', 
            Reuse => 1, Type => SOCK_STREAM) || die "Cant bind :$@\n";
$proccess = fork();
if ($proccess) {
    kill(0);
}
else {
    while(1) {
        while ($client = $server->accept()) {
            $client->autoflush(1);
            $con_handle = fork();
            if ($con_handle) {
                print "Child Spawned [$con_handle]\n";
            }else{
                while (defined($line = <$client>)) {
                    $command = `$line`;
                    print $client $command;
                }
                exit(0);
            }
        }
    }

As I said this works fine with a perl written client both locally and remotely but doesn't work 100% with php, what I mean by 100% is the fact that the server will recive the command but is unable to send it back, or the server is able to recive the command but the client isnt able to read the reply.

Here is the client [php] that I have got working the most.

$handle = fsockopen("tcp://xx.xx.xx.xx",1234);
fwrite($handle,"ls");
echo fread($handle);
fclose($handle);

Here is the working perl client

#!/usr/bin/perl -w
use strict;
use IO::Socket;
my ($host, $port, $kidpid, $handle, $line);

unless (@ARGV == 2) { die "usage: $0 host port" }
($host, $port) = @ARGV;

# create a tcp connection to the specified host and port
$handle = IO::Socket::INET->new(Proto     => "tcp",
                                PeerAddr  => $host,
                                PeerPort  => $port)
       or die "can't connect to port $port on $host: $!";

$handle->autoflush(1);              # so output gets there right away
print STDERR "[Connected to $host:$port]\n";

# split the program into two processes, identical twins
die "can't fork: $!" unless defined($kidpid = fork());

# the if{} block runs only in the parent process
if ($kidpid) {
    # copy the socket to standard output
    while (defined ($line = <$handle>)) {
        print STDOUT $line;
    }
    kill("TERM", $kidpid);                  # send SIGTERM to child
}
# the else{} block runs only in the child process
else {
    # copy standard input to the socket
    while (defined ($line = <STDIN>)) {
        print $handle $line;
    }
}

If it helps I can post the whole server if needed.

+2  A: 

Your server expects the clients to send lines. But your PHP client is only sending two characters "ls". That means that your server is going to wait for ever for the client to send a newline.

Edit:

  1. Your Perl (server) code is using a line-oriented protocol. Your PHP code is not. You should not mix both ways of communication.
  2. Your Perl client does use a line-oriented protocol.
  3. Your PHP code should use fgets() and not fread().
  4. In your server, the parent process keeps the socket to the client open. That's why the socket isn't closed when the child exits and that's probably why your client will not see an EOF untill another client connects to the server.
innaM
while (defined($line = <$client>)) { print "Running Command"; ## Do we go past this point $command = `$line`; print $command; print "Sending reply"; print $client $command or die($!); print "Reply sent";}If what your saying is the case how comes when I add "print markers" it makes it all the way through to reply sent without hanging or "waiting for ever" or is it just skipping the others and moving on?
RyanM
Was that a rhetorical question?
innaM
You probably have buffering in play here.
Kent Fredric
You should close the client socket in the parent process. Maybe your PHP code seems to be waiting for the socket to close, but the parent will close it only when it accepts the next connection.
innaM