mtWeb > Download > HTTP Keep-Alive Connections in PHP

<?php
    
/* $Id: socket.php,v 1.3 2002/09/08 19:25:02 shaggy Exp $ */

/*
Copyright (c) 2001, 2002 by Martin Tsachev. All rights reserved.
mailto:martin@f2o.org
http://martin.f2o.org

Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the conditions available at
http://www.opensource.org/licenses/bsd-license.html
are met.
*/

Class Socket {
    var
$fp = null;
    var
$host;
    var
$timeout = 30;
    var
$maxlen = 4096;

    var
$accept = 'text/html'; // MIME types to accept
    
var $lang = 'en'; // Language to accept

    
var $headers; // response headers
    
var $body; // response body

    
var $status; // HTTP status
    
var $connection; // Connection type: close/keep-alive
    
var $te; // Transfer encoding
    
var $type; // returned MIME type


    
function Socket($host) {
        
$this->host = $host;
    }


    function
setAccept($types) {
        
$this->accept = $types;
    }


    function
connect() {
        
$this->fp = fsockopen($this->host, 80, $errno, $errstr, $this->timeout);

        if (!
$this->fp) {
            return
"Network error: $errstr ($errno)";
        }

        return
0;
    }


    function
disconnect() {
        
fclose($this->fp);
    }


    function
get($uri) {
        
$request =
            
"GET $uri HTTP/1.1\r\n" .
            
"Host: $this->host\r\n" .
            
"Connection: Keep-Alive\r\n" .
            
"Accept: $this->accept\r\n" .
            
"Accept-Language: $this->lang\r\n" .
            
"Accept-Encoding: chunked\r\n" .
            
"User-Agent: PHP/4.2.1\r\n" .
            
"\r\n";

        
fputs($this->fp, $request);

        
$this->headers = fgets($this->fp, $this->maxlen);
        if (!
$this->headers) { // if disconnected meanwhile
            
$this->connect();
            
fputs($this->fp, $request);
            
$this->headers = fgets($this->fp, $this->maxlen);
        }

        
preg_match('|^HTTP.+ (.+) |', $this->headers, $matches);
        
$this->status = $matches[1];

        
$this->type = '';
        
$this->connection = '';
        
$this->te = '';
        
        while (
$line = fgets($this->fp, $this->maxlen)) {
            if (
$line == "\r\n") { break; }

            if (
preg_match('/^Content-Length: (.+)/', $line, $matches)) {
                
$length = (int) trim($matches[1]);
            }

            if (
preg_match('/^Content-Type: (.+)/', $line, $matches)) {
                
$this->type = strtolower(trim($matches[1]));
            }

            if (
preg_match('/^Connection: (.+)/', $line, $matches)) {
                
$this->connection = strtolower(trim($matches[1]));
            }

            if (
preg_match('/^Transfer-Encoding: (.+)/', $line, $matches)) {
                
$this->te = strtolower(trim($matches[1]));
            }

            
$this->headers .= $line;
        }

        
$this->body = '';

        if (
$this->connection == 'close') {
            while (!
feof($this->fp)) {
                
$this->body .= fread($this->fp, $this->maxlen);
            }
            return ;
        }

        if (isset(
$length) and strpos($this->te, 'chunked') === false) {
            
$this->body = fread($this->fp, $length);
            return ;
        }

        
// chunked encoding
        
$length = fgets($this->fp, $this->maxlen);
        
$length = hexdec($length);

        while (
true) {
            if (
$length == 0) { break; }
            
$this->body .= fread($this->fp, $length);

            
fgets($this->fp, $this->maxlen);
            
$length = fgets($this->fp, $this->maxlen);
            
$length = hexdec($length);
        }

        
fgets($this->fp, $this->maxlen);
    }

}
// class Socket
?>