View Single Post
Old 08-16-2008, 07:46 PM   #1 (permalink)
tripy
The Wanderer
 
tripy's Avatar
 
Join Date: Apr 2008
Posts: 7
Thanks: 0
tripy is on a distinguished road
Default PHP socket based communication with a python server

I've been tearing my hairs for the last 13 hours on this..

I have wrote a multi-threaded python scheduler, that listen on a socket for client commands.
On each command received, it does something, write back something to the client and close the connection.
I've developped this to monitor external commands, ran from a website, to be able to kill commands that freeze. The command is a gecko based web client, and sometimes, the library freeze on some pages. Nothing can stop it, except a kill -9 on the server.

So, this server run that client in 1 new thread at each requests, and another thread monitor those client. 1 takes more than 1 minute to complete, a kill signal is sent to him.

At the same time that the server, I have wrote a small python client (20 lines) that works very well, and I thought that it would be easy to port in php, but no luck until now.

This is the python client:
Code:
import socket
import threading
import sys

# Here's our thread:
class ConnectionThread ( threading.Thread ):
  def run ( self ):
    # Connect to the server:
    client = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
    client.connect ( ( 'localhost', 2727 ) )
    client.send ( msg )
    print client.recv ( 1024 )
    client.close()
if __name__ == "__main__":
  msg=sys.argv[1]
  ConnectionThread().start()
Plain dumb, but works like a charm.
I've translated it (with great inspiration taken from the php.net user manual) in php to:
PHP Code:
/*
This is an excerpt from a class, dismiss the $self occurences.
It's just a cop/paste from the main method of the class
*/
$w=1280;
$h=1024;
$W=800;
$H=600;
$cmd=<<<CMD
url:{$this->url}, BrowsWidth:$w, BrowsHeight:$h, outW:$W, outH:$H, maxTime:{$this->maxTime}, minTime:{$this->minTime}, type:{$this->format}, qual:{$this->qual}, crop:{$this->crop}, useMC:1, file:{$this->md5}
CMD;
$sock=fsockopen('127.0.0.1',2727);
$cpt=0;
fwrite($sock$cmdstrlen($cmd));
print 
"done writing command...\n";
$pid="";
while (!
feof($sock)){
  
//we now get back the pid
  
print ">$pid<::$cpt\n------------\n";
  
$cpt++;
  
$pid.=fgets($sock,10);

Basically, I send the "start" command, and I want to get back the pid of the thread running it.
My problem is that my script looks like being stuck in the while loop, where it tries to read the socket.
If I put a length of 1, it goes through the loop without exiting it.
If I put more than 1 as the wanted data length, it seems to hang like it was waiting for more to come.

What seems strange to me, is that the server closes the connection after each answer sent, but php don't seems to see it
This is what the server logs:
Code:
~~~~
command => url:webalis.com, BrowsWidth:1024, BrowsHeight:768, outW:250, outH:187, maxTime:30, minTime:0, type:jpg, qual:50, crop:, useMC:1, file:63fd20cbf455a961e66796a18cbd7fe7
~~~~~~

Thread pid: 52279
5 bytes sent
connection closed
And this is the python code:
Code:
w=webshot(id, self.context)
w.start()
ret=str(id)
print 'Thread pid: %s'%(ret)
nbr=client[0].send(ret)
print '%d bytes sent'%(nbr)
client[0].close()
print 'connection closed'
Stranger yet, if I use a telnet session, it works as expected:
Code:
telnet server 2727
Trying 192.168.50.254...
Connected to server.
Escape character is '^]'.
url:webalis.com   //<== What I have typed
35120             //<== The server answer
Connection closed by foreign host.
I'd hate to resort to a shell_exec("python client.py") rather than using sockets, but for now, it's the direction I see following.
I never had problem like that with php and socket before, but it was always between 2 php processes.

Does anyone here have any idea on how to solve this issue ?
tripy is offline  
Reply With Quote