TalkPHP

TalkPHP (http://www.talkphp.com/forums.php)
-   Advanced PHP Programming (http://www.talkphp.com/advanced-php-programming/)
-   -   PHP socket based communication with a python server (http://www.talkphp.com/advanced-php-programming/3245-php-socket-based-communication-python-server.html)

tripy 08-16-2008 07:46 PM

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 08-16-2008 08:22 PM

Ha !
I've found it....

I had to add a "\n" after each infos sent back. Php stop to read when he received a EOL character...
So much time lost over such a litlle detail...

tony 08-16-2008 09:06 PM

this is a good resource to have, thanks for posting it and find the answer quickly. good to now about the EOL behavior

cad106uk 07-15-2009 03:31 PM

Also having a problem with socket based php communication with a python server
 
Hi

I am hoping someone has some insight into what is happening here. I am also writing a php script to connect to a python server. I have written a simple twisted telnet server (taken from the twisted tutorial) and a simple php client which writes to it. In the logs I can see the PHP client connecting to the server and disconnecting from the twisted server but none of the fwrite commands ever register in the server logs (or anywhere else on the twisted server). However I do not get an error in the PHP script, the fwrite function returns as though the function ran without errors.

the twisted server

PHP Code:

"""The most basic chat protocol possible.

run me with twistd -y chatserver.py, and then connect with multiple
telnet clients to port 1025
"""

from twisted.protocols import basic



class MyChat(basic.LineReceiver):
    
def connectionMade(self):
        print 
"Got new client!"
        
self.factory.clients.append(self)

    
def connectionLost(selfreason):
        print 
"Lost a client!"
        
self.factory.clients.remove(self)

    
def lineReceived(selfline):
        print 
"received"repr(line)
        for 
c in self.factory.clients:
            
c.message(line)

    
def message(selfmessage):
        
self.transport.write(message '\n')


from twisted.internet import protocol
from twisted
.application import serviceinternet

factory 
protocol.ServerFactory()
factory.protocol MyChat
factory
.clients = []

application service.Application("chatserver")
internet.TCPServer(1025factory).setServiceParent(application


The php client

PHP Code:

<?php

$fp 
fsockopen("localhost"1025$errnum$errstr);

if (
$fp) {
    
$tmp "This is a test";
    print 
$tmp;
    print 
fwrite($fp$tmp);
}
fclose($fp);

?>


Does anyone have any idea as to where the data from the fwrite function is going?

Thanks

tony 07-15-2009 03:55 PM

It's been a while since I meddle with sockets and I have never done it with PHP but C++. But I found this article that seems useful and this examples too. Also I you can do it with curl too.
But I am not much help when it comes to sockets

cad106uk 07-15-2009 04:49 PM

Thanks for the documentation
 
Thanks for pointing me to some more documentation to read up on (it is useful stuff). Unfortunately there is nothing here that fixes my problem directly. I'll look into to using the socket_create function to see if that fixes it.

Thanks

cad106uk 07-15-2009 05:34 PM

fixed it
 
Aha,

Tony you where right about the socket_create stuff. After some reading up and re-writing and came up with this as a working php client :)

PHP Code:

<?php

error_reporting
(E_ALL);

echo 
"<h2>TCP/IP Connection</h2>\n";

/* Get the port for the WWW service. */
$service_port 1025;

/* Get the IP address for the target host. */
$address gethostbyname('localhost');

/* Create a TCP/IP socket. */
$socket socket_create(AF_INETSOCK_STREAMSOL_TCP);
if (
$socket === false) {
    echo 
"socket_create() failed: reason: " socket_strerror(socket_last_error()) . "\n";
} else {
    echo 
"OK. $socket\n";
}

echo 
"Attempting to connect to '$address' on port '$service_port'...";
$result socket_connect($socket$address$service_port);
if (
$result === false) {
    echo 
"socket_connect() failed.\nReason: ($result) " socket_strerror(socket_last_error($socket)) . "\n";
} else {
    echo 
"OK.\n";
}

$in "HEAD / HTTP/1.1\r\n";
$in .= "Host: www.example.com\r\n";
$in .= "Connection: Close\r\n\r\n";

echo 
"Sending HTTP HEAD request ... $in";
socket_write($socket$instrlen($in));
echo 
"OK.\n";

echo 
"Closing socket...";
socket_close($socket);
echo 
"OK.\n\n";

?>


tony 07-15-2009 08:20 PM

great! seems simple enough, I need to dive more into php socket programming, probably a project on that. hehe


All times are GMT. The time now is 01:25 AM.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0