PHP_HTTP協議

HTTP協議介紹

重要性:
是使用webservice,仍是rest作大型架構,都離不開對HTTP協議的認識javascript

簡化的說:
webservice = http協議 + XML
Rest = http協議 + JSONphp

各類API,也是經過http + XML/JSON來實現css

作採集,須要對http協議有所瞭解,以及ajax,對http協議理解.html

協議

計算機中的協議和現實中的協議是同樣的,一式雙份/多份
雙方/多方都聽從共同的一個規範,這個規範稱之爲協議.java

ftp, https, http, stmp, pop, tcp/ip 協議...git

URI/URL/URNgithub

// URL: 統一資源定位符
https://v.sf.com:80/index.html?name=user#bbs

// URN:統一資源名稱
ste.org/img.png

URI :統一資源標識符web

  1. URN和URL都屬於URI.
  2. URI能成爲URL的固然就是那個「訪問機制」,「網絡位置」
  3. URN是惟一標識的一部分,就是一個特殊的名字

https默認尋找服務器443端口ajax

名詞解釋:apache

  • OSI:開放系統互連參考模型(Open System Interconnnect 簡稱OSI)
  • TCP:TCP (Transmission Control Protocol 傳輸控制協議)是一種面向鏈接的,可靠的,基於字節流的傳輸層通訊協議。
  • IP:IP(Internet Protocol)網絡之間互連的協議
  • HTTP:HTTP(Hyper Text Transfer Protocol超文本傳輸協議)是互聯網上應用最爲普遍的一種網絡協議。
  • HTTPS:HTTPS (Hyper Text Transfer Protocol over Secure Socket Layer)是以安全爲目標的HTTP通道,簡單講師HTTP的安全版

五層網絡協議

應用層(http/https/websocket/ftp) => 定義:文本傳輸協議
    ↓
傳輸層(tcp/udp) => 定義:端口    
    ↓
網絡層(IP) => 定義:IP
    ↓
鏈路層(mac&數據包) => 定義:數據包,MAC地址
    ↓
實體層(光纜/電纜/交換機/路由/終端...)  => 定義:物理

網絡協議解釋:
解釋1:分別表明TCP協議和IP協議
解釋2:若是按照網絡五層架構,TCP/IP表明除了應用層其它層全部協議簇的統稱

TCP/IP三次握手:

標有syn的數據包
          ----------------->
          標有syn/ack的數據包
  client  <-----------------  server
           標有ack的數據包
          ----------------->

Keep-Alive
HTTP協議初期每次鏈接結束後都會斷開TCP連接,以後HEADERconnection字段定義Keep-Alive(HTTP1.1 默認 持久鏈接),表明若是鏈接雙方若是沒有一方主動斷開都不會斷開TCP鏈接,減小了每次創建HTTP鏈接時進行TCP的鏈接的消耗.

HTTP協議工做流程

當打開一個頁面以後時.

  1. 原始狀態 : 客戶端與服務器之間沒有關係
  2. request 請求

客戶端 --> 服務器 (請求鏈接)
鏈接:就是網絡上的虛擬電路

  1. response 響應

    客戶端 <-- 服務器 (沿着鏈接,返回響應信息)

客戶端,收到響應代碼(HTML代碼,解析文字,圖片)

  1. 斷開鏈接

瀏覽器能發送HTTP協議,HTTP協議必定要瀏覽器來發送麼?
不是,HTTP是一種協議,只要知足,什麼工具均可以發送.
可使用 telnet host port
telnet做用:遠程控制web服務器

回顯功能:
ctrl+]輸入以後,再回車

請求信息和響應信息

clipboard.png

請求

  1. 請求行
  2. 請求頭信息
  3. 請求主體信息 (能夠沒有)
  4. 頭信息結束後和主體信息之間要空行一行

請求行

  • 請求方法
    請求方法:GET,POST,PUT,HEAD,DELTE,TRACE,OPTIONS
  • 請求路徑
  • 所用的協議: 目前通常是HTTP/1.1 0.9 和 1.0 基本不使用

使用telnet來完成HTTP協議的POST請求

POST /github/http/telnet_post.php HTTP/1.1
Host: www.muchai.com
Content-type: application/x-www-form-urlencoded
Content-length: 33

clipboard.png

響應

  1. 響應行
  2. 相應頭信息
  3. 相應主體信息

響應行

  • 協議
  • 狀態碼
  • 狀態文字

clipboard.png

方法與狀態碼

請求方法

請求方法有哪些?

GET, POST, HEAD, PUT, TRACE, DELETE, OPTIONS

HEAD和GET基本一致,只是不返回內容.
好比:只是確認一個內容(照片)是否還存在,不須要返回具體的內容。

PUT: 往服務器資源傳輸內容
TRACE:使用代理上網. 好比用代理訪問www.sf.gg看下代理是否修改HTTP請求,可使用TRACE來測試一下,sf.gg的服務器就會把最後收到的請求返回.

clipboard.png

OPTIONS: 返回服務器可用的請求方法.

注意:這些請求方法雖然是HTTP協議中規定的,但WEB SERVER未必容許或支持這些方法.

  • get: 獲取資源,url傳參,大小2KB
  • post: 傳輸資源,http body, 大小默認8M,1000個input variable
  • put: 傳輸資源,http body,資源更新
  • delete: 刪除資源
  • patch: 傳輸資源,http body,存在的資源局部更新
  • head: 獲取http header
  • options: 獲取支持的method
  • trace: 追蹤,返回請求迴環信息
  • connect: 創建隧道通訊

狀態碼

狀態碼和狀態文字

狀態碼: 是用來反應服務器響應狀況的
最多見的: 200 OK, 404 NOT FOUND,
狀態文字是用來描述狀態碼,便於人觀察

響應中的狀態碼

狀態碼 定義 說明
1xx 信息 接收到請求,繼續處理
2xx 成功 操做成功地收到請求,理解和接受
3xx 重定向 爲了完成請求,必須採起進一步措施
4xx 客戶端錯誤 請求的語法錯誤或不能徹底被知足
5xx 服務端錯誤 服務器沒法完成明顯有效的請求

經常使用的狀態碼:
200 -- 服務器成功返回網頁
301/2 -- 永久/臨時重定向

<?php
header('Location: http://www.sf.gg'); // 默認是 302 重定向
header('Location: http://www.sf.gg', true, 301); // 301 重定向  // 永久重定向 , true參數指的是用301頭信息替換原來的頭信息
?>

304 Not Modified -- 未修改 (客戶端告知服務器請求的資源,時間ETag是否變化)
307 重定向中保持原有的請求數據.(POST重定向以後,數據丟失)

失敗的狀態碼:
404 -- 請求的網頁不存在,地址錯誤。
403 -- 禁止訪問,權限不足。
503 -- 服務器暫時不可用
500 -- 服務器內部錯誤
502(Bad Gateway) -- 網關錯誤(ip設置的時候網關地址錯誤)


  • 200: ok
  • 301: 永久重定向
  • 302: 臨時重定向
  • 303: 臨時重定向,要求用get請求資源
  • 304: not modified, 返回緩存,和重定向無關
  • 307: 臨時重定向,嚴格不從post到get
  • 400: 參數錯誤
  • 401: 未經過http認證
  • 403: forbidden,未受權
  • 404: not found,不存在資源
  • 500: internet server error,代碼錯誤
  • 502: bad gateway,fastcgi返回的內容web server不明白
  • 503: service unavailable,服務不可用
  • 504: gateway timeout,fastcgi響應超時

Header Fields

常見通用頭部

Cache-Control:

  • no-cache: 不緩存過時的緩存
  • no-store: 不緩存

Pragma:

  • no-cache: 不使用緩存,http1.1前的歷史字段

Connection:

  • 控制不在轉發給代理首部字段
  • Keep-Alive/Close:持久鏈接
  • Date: 建立http報文的日期

常見請求頭

Accept:能夠處理的媒體類型和優先級
Host:目標主機域名
Referer: 請求從哪發起的原始資源URI
User-Agent:建立請求的用戶代理名稱
Coolie:cookie信息

常見響應頭

Location: 重定向地址
Server: 被請求的服務web server的信息
Set-Cookie:要設置的cookie信息

  • NAME:要設置的鍵值對
  • expires:cookie過時時間
  • path: 指定發送cookie的目錄
  • domain: 指定發送cookie的域名
  • Secure: 指定以後只有https下才發送cookie
  • HostOnly:指定以後javascript沒法讀取cookie

HTTPS

概念:在http協議上增長了ssl(secure socket layer)層。

SSL層
↓
應用層
↓
傳輸層
↓
網絡層
↓
鏈路層
↓
實體層

HTTPS認證流程

發起請求
                     --------------------------->  server 
                              下發證書
                      <---------------------------   server 
                      證書數字簽名(用證書機構公鑰加密)
                     --------------------------->  證書機構 
                          證書數字簽名驗證經過
client(內置證書機構證書) <---------------------------   證書機構
                      公鑰加密隨機密碼串(將來的共享祕鑰)
                     --------------------------->  server私鑰解密(非對稱加密)
                        SSL協議結束 HTTP協議開始
                      <---------------------------   server(對稱加密)
                            共享祕鑰加密 HTTP
                     --------------------------->  server(對稱加密)
  • 覈對證書:證書機構的公開密鑰驗證整數的數字簽名
  • 公開密鑰加密創建鏈接:非對稱加密
  • 共享密鑰加密

HTTP2

  • 多路複用:多個請求共享一個tcp鏈接
  • 全雙工通訊
  • 必須https://
  • 頭部壓縮
  • 二進制傳輸

socket編程

socket發送,HTTP請求.

/**
     * PHP + socket編程 ,發送HTTP請求
     * 
     * 模擬下載, 註冊,登錄, 批量發帖
     */
    

    // http請求類的接口
    interface Proto {
        // 鏈接URL
        public function conn($url);
        
        // 發送get查詢
        public function get();
        
        // 發送post查詢
        public function post();    
        
        // 關閉鏈接
        public function close();        
                
    } 

    class Http implements Proto {
        
        const CRLF = "\r\n"; // 換行信息 
        
        protected $errno = -1; // 錯誤編號
        protected $errstr = ''; // 錯誤信息
        protected $response = ''; // 響應內容             
        
        protected $urlInfo = null; // URL信息
        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->urlInfo['host']);
        }
        
        /**
         * 設置請求行
         * @param {Stinrg} $method 請求方法 默認GET
         */
        protected function setLine( $method ) {
            $this->line[0] = $method . '  ' . $this->urlInfo['path'] . ' ' . $this->version;
        }
        
        /**
         * 聲明頭信息
         * @param {String} $headerline 頭信息
         */
        protected function setHeader( $headerline ) {
            $this->header[] = $headerline; 
        }
            
        /**
         * 寫主體信息
         * @param {Array} $body 設置body信息
         */    
        protected function setBody( $body ) {
            $this->body[] = http_build_query($body);            
        } 
        
        /**
         * 鏈接URL
         * @param {String} $url 鏈接的URL
         */
        public function conn( $url ) {
            // 分析URL
            $this->urlInfo = parse_url($url);
            
            // 判斷端口
            $this->urlInfo['port'] = isset($this->urlInfo['port']) && $this->urlInfo['port'] == 80 ? $this->urlInfo['port'] : 80; 
            
            // 鏈接
            $this->fh = fsockopen($this->urlInfo['host'], $this->urlInfo['port'], $this->errno, $this->errstr, 3);
            
        }
        
        /**
         * 構造get查詢
         */
        public function get() {
            $this->setLine('GET');
            
            $this->request();
            return $this->response;
        } 
        
        
        /**
         * 請求get數據
         * 請求POST數據
         */
        public function request() {
            // 拼接請求信息
            $req = array_merge($this->line, $this->header, array(''), $this->body, array(''));
            $req = implode(self::CRLF, $req);
            
            // 寫
            fwrite($this->fh, $req);
            
            // 讀取
            while ( !feof($this->fh) ) {
                $this->response .= fread($this->fh, 1024); 
            }
            // 關閉鏈接
            $this->close();
        } 
        
        /**
         * 構造post查詢
         * @param {Array} $body body 的信息
         *      
         */
         
        public function post( $body=array() ) {
            
            // 設置請求行
            $this->setLine('POST');
            
            // 構造主體信息
            $this->setBody($body);
            
            // 設置 Content-type 和  計算Content-length
            $this->setHeader('Content-type: application/x-www-form-urlencoded');
            $this->setHeader('Content-length: ' . strlen($this->body[0]));
            
            $this->request();
            return $this->response;
            
        } 
        
        /**
         * 關閉鏈接
         */
        public function close() {
            fclose($this->fh);
        } 
        
    }

    set_time_limit(0); // 設置腳本最大執行時間

//    $url = 'http://luqi.baijia.baidu.com/article/719576';
    $url = 'http://www.linxingzhang.com/index.php';
    $http = new Http($url);
//    echo $http->get();
    echo $http->post(array('tit' => 'xixi', 'con' => 'pink'));

http協議模擬登錄

須要的登錄信息,提供請求信息,模擬提供.

// content
    $url = 'http://w.coral.qq.com/article/comment/';
    
    $msg = array(
        'targetid' => 1665529109,
        'type' => 1,
        'format' => 'SCRIPT',
        'callback' => 'parent.topCallback',
        'content' => 'backbone',
        '_method' => 'put',
        'g_tk' => 1437957853,
        'code' => 1,
        'source' => 1,
        'subsource' => 0,
        'picture' => ''     
    );
    
    set_time_limit(0); 
    
    $http = new Http($url);
    
    // 模擬頭信息 
    $http->setHeader('cookie: ptui_loginuin=1129507496@qq.com; pt2gguin=o1129507496; uin=o1129507496; skey=@eHnHS7nT1; ptisp=ctc; RK=9gcWWrSXMK; ptcz=ad2886a1a4a2008cdf953cee396e4c18542dd5667d055f98c1cc7363fc1973ff; pac_uid=1_1129507496; o_cookie=1129507496; pgv_info=ssid=s595782189; pgv_pvid=6186477584; uid=324803742');
    $http->setHeader('Referer: http://www.qq.com/coral/coralBeta3/coralMainDom3.0.htm');
    $http->setHeader('Upgrade-Insecure-Requests:1');
    $http->setHeader('User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.75 Safari/537.36');
    
//    echo $http->post( $msg );
    
    file_put_contents('./res.html', $http->post( $msg ));
    echo 'ook';

referer頭與防盜鏈

網站統計

網站統計結果,如何知道用戶從那些渠道中進入本網站?
統計時,是如何得知用戶從哪兒來到本網站?

在HTTP協議中,頭信息裏,有一個重要的選項:referer
referer:表明網頁的來源,即上一頁的地址.
若是直接在瀏覽器地址欄上輸入,進入網頁,則沒有referer頭.

如何配置apache服務器用於圖片防盜鏈

原理:在web服務器層面,根據http協議的referer頭信息來判斷。若是來自站外,則統一重寫到一個很小的防盜鏈提醒的圖片上.(url重寫)

  • apache重寫模塊 mod_rewrite。(打開mod_rewrite.so)
LoadModule rewrite_module modules/mod_rewrite.so
開啓後,支持重寫模塊.

* 在須要防盜的網站或目錄,寫.htaccess文件,並指定防盜鏈規則.

如何指定,分析referer,若是不是來自本站,從寫url.

重寫規則

那種狀況重寫:

是jpeg/jpg/git/png圖片時.
是referer頭信息與localhost不匹配時重寫.

> 如何重寫

統一rewirte 到 某個防盜鏈圖片.

mod_rewrite

.hatccess文件:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} .*\.(jpg|jpeg|git|png) [NC]
RewriteCond %{HTTP_REFERER} !muchai.com [NC]
RewriteRule .* http://linxingzhang.com/blog/img/weixin.jpg

採集

模擬referer中的信息來請求數據.

$http = new Http('http://linxingzhang.com/blog/img/weixin.jpg');
    
    $http->setHeader('Referer: http://www.muchai.com');
    $res = $http->get();
    
    file_put_contents('./xixi.jpg', substr(strstr($res, "\r\n\r\n"), 4));

http協議緩存控制

圖片的下載:
第一次請求 200ok
第二次請求 304 not modified(未修改狀態)

在網絡上有一些緩存服務器,瀏覽器自身也有緩存功能。
當第一次訪問某圖片時,正常下載圖片,返回值200
基於一個前提(圖片不會常常改動),服務器在返回200的同時,還返回該圖片的"簽名"Etag. (簽名:圖片的指紋)
當瀏覽器再次訪問的同時去服務器校驗"指紋",若是圖片沒有變化。直接使用緩存中的圖片.減輕的服務器的負擔.

觀察請求數據:

第一次訪問
請求頭:

clipboard.png

相應頭:

clipboard.png

第二次請求
請求頭

clipboard.png

若是 自"Wed, 14 Dec 2016 15:41:45 GMT" 這個時間點之後,圖片修改過,則從新請求。
若是圖片最新的ETag的值和 If-None-Match的值不匹配則從新匹配,則從新請求。
響應頭

clipboard.png

若是是304時,瀏覽器從本地取值.

若是網站比較大,有N臺緩存服務器,那麼這N臺服務器,主服務器如何處理主服務器上的文件

  1. 要不要緩存 ?
  2. 緩存多久?
    緩存服務器與主服務器之間,應該有一些協議來講明這兩個問題。

使用什麼協議,來講明這兩個問題。
使用頭信息,cache-control 來控制。
使用方法:
相關模塊: mod_expires.
在服務器,打開apache的expires擴展. 利用該擴展,來控制圖片,css,html等緩存的生存週期及是否緩存.

打開httpd.conf配置項

LoadModule expires_module modules/mod_expires.so

.htaccess 文件配置中.

ExpiresDefault "<base> [plus] {<num> <type>}*"
ExpiresByType type/encoding "<base> [plus] {<num> <type>}>*"

ExpiresDefault 是設置默認的緩存參數
ExpiresByType是按照文件類型來設置獨特的緩存參數.

base 基於那個時間點計算緩存有效期
參數:
access/now: 基於請求響應的那一瞬間. (例如:今後瞬間到一個月以後)
modification: 基於被請求文件最後修改日期來計算. (例如:最後修改日期後一週內)

num: 緩存時間的大小 (例如:30)
type: 緩存的單位(例如:天)

jpeg圖片設置一個月的緩存週期

ExpiresActive On
ExpiresByType image/jpeg "access plus 30 days"

若是在集羣環境裏,緩存服務器獲得此圖片,將會認爲在一個月內有效,減輕了主服務器的負擔。

設置服務器,不讓存在緩存.

例如:有些我的信息,不容許緩存服務器,必須到主服務器去請求.

Control-cache: no-store,must-revalidate; // 不容許緩存,必須去主服務器驗證.

利用apache的header模塊
開啓httpd.conf中的header模塊

LoadModule headers_module modules/mod_headers.so

clipboard.png

<FilesMatch "\.(jpg)$">
header set Cache-Control: "no-store,must-revalidate"
</FilesMatch>

http內容壓縮

爲了提升網頁在網絡上的傳輸速度.服務器對主體信息進行壓縮.
常見的,gzip壓縮,deflate壓縮,compress壓縮以及sdch壓縮.

壓縮的過程:

服務器返回壓縮內容,客戶端接收到壓縮,再解壓縮,再渲染頁面.
Content-Length壓縮後的長度
clipboard.png

實際渲染的文件大小:

clipboard.png

如何在apache啓用的壓縮功能?

  • 開啓deflate模塊,或者gzip模塊
LoadModule deflate_module modules/mod_deflate.so
  • conf文件中,配置:
<ifmodule mod_deflate.c>
DeflateCompressionLevel 6
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/atom_xml
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE image/svg+xml
</ifmodule>

爲何要指定文件類型壓縮.

  1. 壓縮須要耗CUP資源
  2. 圖片/視頻等文件,壓縮效果很差.

通常指定壓縮文本格式的文件.

服務器如何知道瀏覽器支持gzip壓縮

客戶端容許發送Accept-Encoding信息.與服務器協商.(協商頭信息)

clipboard.png

comet方向ajax

http協議+持久鏈接+分塊傳輸 => 反向ajax
反向ajax又叫:comet,server push,服務器推技術.

應用範圍:網頁聊天服務器,新浪微博在線聊天,google mail網頁聊天.

原理:HTTP協議的特色,鏈接--斷開.

具體什麼時間斷開?
服務器響應content-length,收到指定length長度的內容時,也就斷開.

在http1.1協議中,容許不寫content-length。(好比要發送的內容長度確實不知道)這是,須要一個特殊的content-typechunked

分塊傳輸:

clipboard.png

<?php

    set_time_limit(0);
    
    ob_start();
    
    $pad = str_repeat("  ", 4000);
    echo $pad, '<br />';
    ob_flush();
    flush(); // 把產生的內容當即返回給瀏覽器,而不要等待瀏覽器結束
     
     
    $i = 1;
    while ( $i++ ) {
        echo $pad, '<br />';
        echo $i, '<br />';
            
        ob_flush();
        flush(); 
        sleep(1);
    }
    
    /**
     * 
     * 即時通訊.
     * 
     * 服務器端不間斷,推送信息. 到客戶端.
     */     
     
?>
相關文章
相關標籤/搜索