View Single Post
Old 09-10-2012, 12:26 AM   PM User | #1
vroom
New Coder

 
Join Date: Sep 2012
Posts: 71
Thanks: 0
Thanked 8 Times in 8 Posts
vroom is an unknown quantity at this point
Asynchronous GET/POST Requests (PHP5)

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
// ##########################################################################

class AsyncTCP
{
   
// Connection parameters
   // ---------------------
   
private $transport;
   private 
$host;
   private 
$port;
   private 
$uri;
   private 
$postdata;
   private 
$timeout;

   
// Connected socket details
   // ------------------------
   
private $s;
   private 
$status;
   private 
$error;
   private 
$written;
   private 
$data;

   
// ***********************************************************************
   // 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 ); }
   public function 
wasError()  { return ( $this->error ); }
   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->stream_socket_client($this->transport."://".$this->host.":".$this->port
                                     
,$errno
                                     
,$errstr
                                     
,$this->timeout
                                     
,STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT);

      
$this->status 'connected';
      if ( 
$errno )
      {
         
$this->error $errno;
         
$this->status 'connect failed: $errrstr ($errno)';
      }

      return 
$this->error;
   }

   
// ***********************************************************************
   // 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;

      
$sockets['id']  = $this->s;
      
$read           $sockets;
      
$write          $sockets;
      
$except         null;

      
$n stream_select($read$write$except$seconds$usec);

      if ( 
$n )
      {
         
// Perform available read operations
         // ---------------------------------
         
foreach ($read as $r)
         {
            
$chunk fread($r$readlen);
            if ( 
$chunk === FALSE )
               
$this->status 'connect or read error';
            else
            {
               
$this->data  .= $chunk;
               
$this->status 'reading';
            }

            if ( 
strlen($chunk) < $readlen )
               
$this->status 'done';
         }

         
// Perform pending write operations
         // --------------------------------
         
foreach ($write as $w)
         {
            if ( !
$this->written )
            {
               
// Adjust for GET or POST requests
               // -------------------------------
               
$method 'GET';
               
$host   $this->host;
               
$port   $this->port;
               
$uri    $this->uri;
               
$headers "Host: $host\r\n";

               if ( 
strlen($this->postdata) )
               {
                  
$method 'POST';
                  
$length strlen($this->postdata);
                  
$headers .= "Content-type: application/x-www-form-urlencoded\r\n";
                  
$headers .= "Content-length: $length\r\n";
               }
               
$headers .= "\r\n";

               
// Build the message bundle
               // ------------------------
               
$msg  "$method $uri HTTP/1.0\r\n";
               
$msg .= $headers;
               
$msg .= $this->postdata;

               
fwrite($w,$msg);
               
$this->status  'sent; waiting for response';
               
$this->written 1;
            }
         }

      } 
// if ( n )

      
return $this->status;

   } 
// function advance()

// class AsyncTCP

Last edited by vroom; 09-10-2012 at 02:25 AM..
vroom is offline   Reply With Quote