RyanM
RyanM

Reputation: 53

PHP To Perl Socket Communication

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.

Upvotes: 4

Views: 2101

Answers (1)

innaM
innaM

Reputation: 47899

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.

Upvotes: 2

Related Questions