The following PHP5 snippet defines an AsyncTCP class that will allow you to open and manage multiple requests to remote servers simultaneously.
While I obviously didn't invent the concept I have wrapped what I've seen within a class, added the ability to use either GET or POST, and created a very simple test script to show how it works (to follow).
PHP Code:
<?php
// ########################################################################## // Name: AsyncTCP.php // Date: 09-Sep-2012 // Prog: gvroom [at] gmail.com (http://hackedcpu.com/) // // Desc: Provide asynchronous TCP/IP communication. Script will continue to // run and allow retrieval of message (if desired) after some or all of // the base functionality has completed. // // Note: This is not expected to be used (advanced) in a tight loop. Caller // is expected to use sleep() or microsleep() to release CPU. // // Source: http://www.codingforums.com/showthread.php?t=272694 // ##########################################################################
// *********************************************************************** // The timeout variable is used for connections only. Socket timeouts // are defined in the advance function. // *********************************************************************** public function __construct($transport,$host,$port,$uri,$postdata='',$timeout=7) { $this->transport = $transport; // tcp, ssl $this->host = $host; // domain.com, www.domain.com $this->port = $port; // 80, 8080, 443 $this->uri = $uri; // /xmlapi.php /x.php?token=abc $this->postdata = $postdata; // properly encoded $this->timeout = $timeout; // 5, 20
$this->s = null; // no connection yet $this->status = 'ready'; // no status yet $this->error = 0; // no errors yet $this->written = 0; // not written yet $this->data = ''; // accumulated response }
// *********************************************************************** // Simple status checks // *********************************************************************** public function isReady() { return ( $this->status == 'ready'); } public function isDone() { return ( $this->status == 'done' || $this->error > 0); } public function isWritten() { return ( $this->written > 0 ); } public function wasError() { return ( $this->error > 0 ); } public function getStatus() { return ( $this->status ); } public function getData() { return ( $this->data); }
// *********************************************************************** // Connect to the remote server. Unfortunately, based on the time taken // to connect this appears not be an asynchronous event... though the read // and write management certainly is. // *********************************************************************** public function connect() { $errno = 0; $errstr = ''; $this->s = stream_socket_client($this->transport."://".$this->host.":".$this->port ,$errno ,$errstr ,$this->timeout ,STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT);
// *********************************************************************** // Manage the connection. Basically, advance through a series of actions // to send a request and get the response. // *********************************************************************** public function advance() { static $sockets = array(); static $seconds = 0; static $usec = 100; static $readlen = 8192;
This is a run against two Google servers (both GET requests one via SSL). Notice how both connections "advance" to different status values at different times. There may be a bug in the read logic as the first response may be cut off (I'll edit the original post if/when I find it).
... issueing c1 connect ... c1 connected at elapsed 0.0012650
... issueing c2 connect ... c2 connected at elapsed 0.0163491
elapsed: 0.0165250
... c1: sent; waiting for response
... c2: sent; waiting for response
elapsed: 0.0229831
... c1: sent; waiting for response
... c2: sent; waiting for response
elapsed: 0.0282569
... c1: done
... c2: sent; waiting for response
elapsed: 0.0334899
... c1: done
... c2: done
c1:
HTTP/1.1 200 OK Server: nginx/1.1.19 Date: Sun, 09 Sep 2012 23:01:45 GMT Content-Type: text/html; charset=utf-8 Connection: close X-Powered-By: PHP/5.3.10-1ubuntu3.2 Set-Cookie: PHPSESSID=fag2vg36ormvo5eopd86lmu3r6; expires=Sun, 16-Sep-2012 23:01:45 GMT; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache <br> <b>H A C K E D C P U D E M O</b><br> <br> Enter a small amount of English language text (up to 512 bytes):<br> <form method="post" action=""> <textarea name="textin" rows="9" cols="100">this is my input text.</textarea><br> <input type="submit" name="submit" value="Go"><br> </form> Processing...<br> <br> this: 1<br> is: 1<br> my: 1<br> input: 2<br> text: 1<br> <br> 5 tokens found containing 5 unique words<br> <br> <hr> PHP processing took 0.00458884 seconds<br>