TalkPHP
 
 
Account Login
Latest Articles
» The basic usage of PHPTAL, a XML/XHTML template library for PHP
» Vulnerable methods and the areas they are commonly trusted in.
» Simple way to protect a form from bot
» The Basics On: How Session Stealing Works
» How to keep your forms from double posting data
IRC Channel
IRC Speech Bubble Join the friendly bunch on IRC...
(#TalkPHP on Freenode)

...Also available via a web interface.

See this thread for information on the TalkPHP Free Hugs Initiative™. Subject to availability.
Associates
Associates
CSS Tutorials
Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old 08-16-2008, 07:46 PM   #1 (permalink)
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
Old 08-16-2008, 08:22 PM   #2 (permalink)
The Wanderer
 
tripy's Avatar
 
Join Date: Apr 2008
Posts: 7
Thanks: 0
tripy is on a distinguished road
Default

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...
tripy is offline  
Reply With Quote
Old 08-16-2008, 09:06 PM   #3 (permalink)
The Addict
 
tony's Avatar
 
Join Date: Aug 2008
Posts: 336
Thanks: 8
tony is on a distinguished road
Default

this is a good resource to have, thanks for posting it and find the answer quickly. good to now about the EOL behavior
tony is offline  
Reply With Quote
Old 07-15-2009, 03:31 PM   #4 (permalink)
The Visitor
 
Join Date: Jul 2009
Posts: 3
Thanks: 0
cad106uk is on a distinguished road
Default 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
cad106uk is offline  
Reply With Quote
Old 07-15-2009, 03:55 PM   #5 (permalink)
The Addict
 
tony's Avatar
 
Join Date: Aug 2008
Posts: 336
Thanks: 8
tony is on a distinguished road
Default

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
tony is offline  
Reply With Quote
Old 07-15-2009, 04:49 PM   #6 (permalink)
The Visitor
 
Join Date: Jul 2009
Posts: 3
Thanks: 0
cad106uk is on a distinguished road
Default 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 is offline  
Reply With Quote
Old 07-15-2009, 05:34 PM   #7 (permalink)
The Visitor
 
Join Date: Jul 2009
Posts: 3
Thanks: 0
cad106uk is on a distinguished road
Default 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";

?>
cad106uk is offline  
Reply With Quote
Old 07-15-2009, 08:20 PM   #8 (permalink)
The Addict
 
tony's Avatar
 
Join Date: Aug 2008
Posts: 336
Thanks: 8
tony is on a distinguished road
Default

great! seems simple enough, I need to dive more into php socket programming, probably a project on that. hehe
tony is offline  
Reply With Quote
Reply



Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


All times are GMT. The time now is 12:32 AM.

 
     

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0
Inactive Reminders By Icora Web Design