php 利用socket發送GET,POST請求

  做爲php程序員必定會接觸http協議,也只有深刻了解http協議,編程水平纔會更進一步。最近我一直在學習php的關於http的編程,許多東西恍然大悟,受益不淺。但願分享給你們。本文須要有必定http基礎的開發者閱讀。php

  今天給你們帶來的是如何利用socket發送GET,POST請求。我借用燕十八老師封裝好的一個Http類給進行說明。程序員

  在平常編程中相信不少人和我同樣大部分時間是利用瀏覽器向服務器提出GET,POST請求,那麼能否利用其它方式提出GET,POST請求呢?答案必然是確定的。瞭解過HTTP協議的人知道,瀏覽器提交請求的實質是向服務器發送一個請求信息,這個請求信息有請求行,請求頭,請求體(非必須)構成。服務器根據請求信息返回一個響應信息。鏈接斷開。編程

   HTTP請求的格式以下所示:數組

1 <request-line>
2 <headers>
3 <blank line>
4 [<request-body>]

 

  HTTP響應的格式與請求的格式十分類似:瀏覽器

<status-line>
<headers>
<blank line>

[<response-body>]

  咱們能夠利用HTTP發送請求的原理,能夠從新考慮利用socket發送HTTP請求。服務器

  Socket的英文原義是「孔」或「插座」。一般也稱做「套接字」,用於描述IP地址和端口,是一個通訊鏈的句柄,能夠用來實現不一樣虛擬機或不一樣計算機之間的通訊。在Internet上的主機通常運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個Socket,並綁定到一個端口上,不一樣的端口對應於不一樣的服務。如此看來,其實利用socket操做遠程文件和讀寫本地的文件同樣容易,把本地文件當作經過硬件傳輸,遠程文件經過網線傳輸就好了。app

  於是能夠將發送請求的考慮成 創建鏈接->打開socket接口(fsockopen())->寫入請求(fwrite())->讀出響應(fread()->關閉文件(fclose())。話很少說,直接上代碼:socket

  

<?php 

interface Proto {
    // 鏈接url
    function conn($url);

    //發送get查詢
    function get();

    // 發送post查詢
    function post();

    // 關閉鏈接
    function close();
}



class Http implements Proto {

    const CRLF  = "\r\n";

    protected $errno = -1;
    protected $errstr = '';
    protected $response = '';

    protected $url = null;
    protected $version = 'HTTP/1.1';
    protected $fh = null;
    
    protected $line = array();
    protected $header = array();
    protected $body = array();

    
    public function __construct($url) {
        $this->conn($url);
        $this->setHeader('Host: ' . $this->url['host']);
    }

    // 此方法負責寫請求行
    protected function setLine($method) {
        $this->line[0] = $method . ' ' . $this->url['path'] . '?' .$this->url['query'] . ' '. $this->version;
    }

    // 此方法負責寫頭信息
    public function setHeader($headerline) {
        $this->header[] = $headerline; 
    }

    // 此方法負責寫主體信息
    protected function setBody($body) {
         $this->body[] = http_build_query($body);
    }


    // 鏈接url
    public function conn($url) {
        $this->url = parse_url($url);
        // 判斷端口
        if(!isset($this->url['port'])) {
            $this->url['port'] = 80;
        }

        // 判斷query
        if(!isset($this->url['query'])) {
            $this->url['query'] = '';
        }

        $this->fh = fsockopen($this->url['host'],$this->url['port'],$this->errno,$this->errstr,3);
    }

    //構造get請求的數據
    public function get() {
        $this->setLine('GET');
        $this->request();
        return $this->response;
    }

    // 構造post查詢的數據
    public function post($body = array()) {      
        $this->setLine('POST');

        // 設計content-type
        $this->setHeader('Content-type: application/x-www-form-urlencoded');
        
        // 設計主體信息,比GET不同的地方
        $this->setBody($body);


        // 計算content-length
        $this->setHeader('Content-length: ' . strlen($this->body[0]));

        $this->request();

        return $this->response;
    }

    // 真正請求
    public function request() {
        // 把請求行,頭信息,實體信息 放在一個數組裏,便於拼接
        $req = array_merge($this->line,$this->header,array(''),$this->body,array(''));
        //print_r($req);

        $req = implode(self::CRLF,$req); 
        //echo $req; exit;

        fwrite($this->fh,$req);
        
        while(!feof($this->fh)) {
            $this->response .= fread($this->fh,1024);
        }

        $this->close(); // 關閉鏈接
    }


    // 關閉鏈接
    public function close() {
        fclose($this->fh);
    }

}

 

      利用此類發送一個簡單的GET請求:post

<?php

//記得引用Http類
$url="http://home.cnblogs.com/u/DeanChopper/"; $http=new Http($url); $response=$http->get(); print_r($response);

  返回值爲信息,能夠對響應信息進行進一步處理,獲得本身想獲得的內容。學習

相關文章
相關標籤/搜索