http--请求工具类

http请求报文内容本身比较简单,今天仿照别人的代码手写了一个请求客户端,目的是加深了解请求都需要哪些部分。

整个http事务大概分为以下流程

  •     通过dns解析出ip和端口
  •     三次握手建立tcp连接通道
  •     客户端开始构造、发送http请求,服务端接收并处理请求,然后构造响应报文返回给客户端
  •     断开tcp连接(keep-alive除外)

当然,实际的http事务过程可能更为复杂,并不与目的服务器直接建立连接,中间或许会经历各种各样的代理过程

http请求报文主要结构

  • 请求行

            方法  资源路径   协议版本

  • 请求首部

            请求首部键名   对应值

  • 请求主体

            请求体

 

 

下面是有关请求报文构建代码:

<?php

//http客户端工具类
class HttpClient
{
    //行分割付
    private $sp = "\r\n";
    //请求行
    private $requestLine = "";
    //请求首部
    private $requestHeader = "";
    //请求首部数组
    private $header = [];
    //请求主体
    private $requestBody = "";
    //全部请求信息   请求行+请求首部+请求体
    private $requestInfo = "";
    //暂存请求地址相关信息
    private $urlinfo;
    //存储套接字
    private $fp = null; 
    //协议
    private $protocol = 'HTTP/1.1'; 
    //存储响应报文
    private $responseInfo="";

    private static $http = null;// Http对象单例

    protected function __construct(){}

    
    //单例模式
    public static function create(){
        if ( self::$http === null ) {  
            self::$http = new HttpClient(); 
        } 
        return self::$http; 
    }
    
    //请求的url
    public function init($url)
    {
        $this->urlinfo = parse_url($url);
        $this->header['Host'] = $this->urlinfo['host'];
        return $this;
    }
    
    //请求头信息,请求主体信息
    public function get($headers = [],$data=[])
    {
        $this->header = array_merge($this->header,$headers);
        if(count($data)){
            $this->urlinfo['path'] = $this->urlinfo['path'].'?'.http_build_query($data);
        }
        return $this->request('GET');
    }

    //请求头信息,请求主体信息
    public function post($headers = [],$data=[])
    {
        $this->header = array_merge($this->header,$headers);
        if(count($data)){
            $this->requestBody = http_build_query($data);
            $this->header['Content-Type'] = 'application/x-www-form-urlencoded'; 
            $this->header['Content-Length'] = strlen(http_build_query($data)); 
        }
        return $this->request('POST');
    }

    private function request($method)
    {
        //请求行
       $this->requestLine = $method.' '.$this->urlinfo['path'].' '.$this->protocol.$this->sp;
       //拼接请求有
       $header = "";
       foreach ($this->header as $key => $value) {
               $header.=$key.": ".$value.$this->sp;
       }
       $this->requestHeader = $header;

       $this->requestInfo = $this->requestLine.$this->requestHeader.$this->sp;

       //如果请求主体不为空
        if($this->requestBody != ""){
           $this->requestInfo.= $this->requestBody;
        }
        
        $port = isset($this->urlinfo['port']) ? isset($this->urlinfo['port']) : '80'; 
        $this->fp = fsockopen($this->urlinfo['host'], $port, $errno, $errstr); 

        if ( !$this->fp ) { 
            echo $errstr.'('.$errno.')'; 
            return false; 
        } 
        if (fwrite($this->fp, $this->requestInfo) ) { 
            $str = ""; 
            while ( !feof($this->fp) ) { 
                $str .= fread($this->fp,1024); 
            } 
            $this->responseInfo = $str; 
        } 
        fclose($this->fp); 
        return $this->responseInfo; 

    }



}


$url = 'http://www.baidu.com/index.php';

echo HttpClient::create()->init($url)->post(array( 
    'User-Agent' => 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36',
    'Content-Type'=>'text/html; charset=utf-8',
    'Content-Length'=>20 
),['aaaaaaaaaa'=>'bbbbbbbbbb']);

/*
echo HttpClient::create()->init($url)->get(array( 
    'User-Agent' => 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36',
    'Content-Type'=>'text/html; charset=utf-8',
),['aaaaaaaaaa'=>'bbbbbbbbbb']);
*/

 

推荐一个比较简易学习http报文构建过程源码,代码量少,比较适合我这种看代码头疼的人看,哈哈。

http://scripts.incutio.com/httpclient/HttpClient.tar.gz

posted @ 2018-04-19 18:26  rcj_飞翔  阅读(101)  评论(0)    收藏  举报