1. 程式人生 > >Linux網路程式設計---詳解HTTP協議

Linux網路程式設計---詳解HTTP協議

HTTP 簡介

HTTP協議是Hyper Text Transfer Protocol(超文字傳輸協議)的縮寫,是用於從全球資訊網(WWW:World Wide Web )伺服器傳輸超文字到本地瀏覽器的傳送協議。。
HTTP是一個基於TCP/IP通訊協議來傳遞資料(HTML 檔案, 圖片檔案, 查詢結果等)。

HTTP 工作原理

HTTP協議工作於客戶端-服務端架構上。瀏覽器作為HTTP客戶端通過URL向HTTP服務端即WEB伺服器傳送所有請求。
Web伺服器有:Apache伺服器,IIS伺服器(Internet Information Services)等。
HTTP預設埠號為80,但是你也可以改為8080或者其他埠。

HTTP三個特點:

HTTP是基於客戶端/服務端(C/S)的架構模型,通過一個可靠的連結來交換資訊,是一個無狀態的請求/響應協議。

HTTP是無連線: 無連線的含義是限制每次連線只處理一個請求。伺服器處理完客戶的請求,並收到客戶的應答後,即斷開連線。採用這種方式可以節省傳輸時間。
HTTP是媒體獨立的: 這意味著,只要客戶端和伺服器知道如何處理的資料內容,任何型別的資料都可以通過HTTP傳送。客戶端以及伺服器指定使用適合的MIME-type內容型別。
HTTP是無狀態: HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺少狀態意味著如果後續處理需要前面的資訊,則它必須重傳,這樣可能導致每次連線傳送的資料量增大。另一方面,在伺服器不需要先前資訊時它的應答就較快。

HTTP使用統一資源識別符號(Uniform Resource Identifiers, URI)來傳輸資料和建立連線。

認識URL(Uniform Resource Identifiers, URI)

平時我們俗稱的 “⺴址” 其實就是說的 URL,我們知道瀏覽器作為HTTP客戶端給是通過URL給HTTP服務端傳送請求進行通訊。所謂的URL就是我們通常所說的網址,我們來看下他的組成:

URL格式:
協議方案名://認證資訊@伺服器地址:埠號/請求的資源路徑?query_string#片段識別符號
例如,我們在百度搜索C++,看下它的URL。
在這裡插入圖片描述

https://www.baidu.
com/s?wd=C%2B%2B&rsv_spt=1&rsv_iqid=0xd99175460001909d&issp=1&f=3&rsv_bp=0&rsv_idx=2& ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=2&rsv_sug1=2&rsv_sug7=001&rsv_sug2=1&rsp=0& rsv_sug9=es_2_1&rsv_sug4=4546&rsv_sug=9

注意:為了能看清楚,所以每一行進行了回車換行,本來的URL是一個連續的一段網址。
下面我們來對比百度的這個網址和普通的URL有什麼區別。
== 協議方案名:==顧名思義,指的是協議方案名字。 我們採用的就是http協議傳送請求,所以前面就是http;http協議是明文傳輸,所以不安全,因此現在基本都是https,https其實就是http的加密版。後面會有專門的部落格介紹https。

認證資訊: 認證資訊就相當於登陸資訊。 對於http協議,他的認證資訊就夾在URL中,我們使用者用肉眼就看一看得見他的登入名和密碼,所以很不安全;而https通過加密之後,這些認證資訊會加密,也就不會直接放在URL中,所以比較安全,因此我們第二幅圖URL中就沒有認證資訊這一塊。

伺服器地址: 指的就是你要請求的伺服器的地址,也就是網址。

埠號: 指你要請求的是伺服器的某個地址對應的程式入口地址。 如果不加埠號,http則預設是80號埠,https是443號埠。這個埠號無符號短整型(0-65535),0-1024不推薦使用,因為是知名協議預留埠。

/請求的資源路徑: 請求的根目錄資源路徑。(這個跟目錄其實是相對根目錄,意思就是URL中上看的是一個根目錄,但對應到伺服器上時其實是一個子目錄)。 如果沒有資源路徑,那麼預設是/index.html,例如你訪問 www.baidu.comwww.baidu.com/index.html 是同一個頁面。

?query_string(查詢字串): 就是你要搜尋的內容。這個內容通過urlencode(URL編碼)成一個字串。這個字串是用&符號連線成的多個鍵值對(key=val&key=val&…)。

#片段識別符號:(相當於標籤),例如第一張圖,瀏覽器讀取URL後,會自動將#ch1位置滾動至可視區域。如果沒有片段識別符號,那直接從頭開始顯示。 我們注意到搜尋C++的時候在它的URL中並沒有顯示C++這些字元。那麼原因就在於他將這些字元進行了編碼。

urlencode/urldecode(URL編碼/解碼)

因為url中特殊字元在很多地方都有特殊含義,因此為了防止我們提交的資料中也包含特殊字元造成歧義,因此對我們提交的資料進行url編碼操作.注意轉義只是轉的提交的字串。

URL編碼操作: 每個字元是一個位元組,即8位。然後將特殊字元高四位轉換為16進位制數字,低四位轉換為16進位制數字,並且為了區分這是轉換過的字元,所以在兩個16進位制數字之前都加上一個轉義字元%。如:+ 對應 0010 1011 ,0010對應2,1011對應b,所以C++轉換過的字元就是C%2b%2b。
我們檢視上面的百度URL就可以找到wd=C%2b%2b,這就是我們搜尋欄輸入的內容,後面的一系列用&連線起來的鍵值對則用於標識請求的其他資訊。URL編碼只是轉義的我們搜尋欄中提交的字串。

URL編碼操作: 解碼操作和編碼剛好互逆。

說了這麼多,終於到了HTTP,我們下來看HTTP協議的格式。

HTTP請求

一個HTTP"客戶端"是一個應用程式(Web瀏覽器或其他任何客戶端),通過連線到伺服器達到向伺服器傳送一個或多個HTTP的請求的目的。
客戶端傳送一個HTTP請求到伺服器的請求訊息包括以下格式:請求行(request line)、請求頭部(header)、空行和請求資料四個部分組成,請求協議格式分了四個部分

在這裡插入圖片描述

GET /hello.txt HTTP/1.1//緊接著這塊是回車換行,即\r\n
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3//緊接著這塊是回車換行,即\r\n
Host: www.example.com//緊接著這塊是回車換行,即\r\n
Accept-Language: en, mi//緊接著這塊是回車換行,即\r\n
//這塊是空行,/r/n
//接著這塊是請求正文

HTTP 協議的 8 種請求型別(方法)

HTTP1.0定義了三種請求方法: GET, POST 和 HEAD方法。
HTTP1.1新增了五種請求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。

具體介紹如下:
GET: 向特定的資源發出請求。其更多的是獲取資源,沒有請求正文,能夠提交的url長度是有限的(這是它的缺陷),早期最大是1K,現在4-8k。

POST: 向指定資源提交資料進行處理請求(例如提交表單或者上傳檔案)。資料被包含在請求體中。POST請求可能會導致新的資源的建立和/或已有資源的修改。更多提交表單資料,有正文,提交的資料是在正文中,正文沒有長度限制。
HEAD: 向伺服器索要與GET請求相一致的響應,只不過響應體將不會被返回。這一方法可以在不必傳輸整個響應內容的情況下,就可以獲取包含在響應訊息頭中的元資訊。

OPTIONS: 返回伺服器針對特定資源所支援的HTTP請求方法。也可以利用向Web伺服器傳送’*'的請求來測試伺服器的功能性。

PUT: 向指定資源位置上傳其最新內容。
DELETE: 請求伺服器刪除 Request-URI 所標識的資源。
TRACE: 回顯伺服器收到的請求,主要用於測試或診斷。
CONNECT: HTTP/1.1 協議中預留給能夠將連線改為管道方式的代理伺服器。
雖然 HTTP 的請求方式有 8 種,但是我們在實際應用中常用的也就是 get 和 post,其他請求方式也都可以通過這兩種方式間接的來實現。

HTTP響應

在這裡插入圖片描述

HTTP/1.1 200 OK	//狀態行,分別為協議版本、狀態碼、狀態描述符
Date: Mon, 27 Jul 2009 12:28:53 GMT//響應報頭
Server: Apache//響應報頭
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT//響應報頭
ETag: "34aa387-d-1568eb00"//響應報頭
Accept-Ranges: bytes//響應報頭
Content-Length: 51//響應報頭
Vary: Accept-Encoding//響應報頭
Content-Type: text/plain//響應報頭
//空行,即\r\n
//這裡是響應正文

HTTP 響應頭資訊

Allow: 伺服器支援哪些請求方法(如GET、POST等)。

Content-Length : 表示內容長度。只有當瀏覽器使用持久HTTP連線時才需要這個資料。如果你想要利用持久連線的優勢,可以把輸出文件寫入 ByteArrayOutputStream,完成後檢視其大小,然後把該值放入Content-Length頭,最後通過byteArrayStream.writeTo(response.getOutputStream()傳送內容。

Content-Type : 表示後面的文件屬於什麼MIME型別。Servlet預設為text/plain,但通常需要顯式地指定為text/html。由於經常要設定Content-Type,因此HttpServletResponse提供了一個專用的方法setContentType。

Date: 當前的GMT時間。你可以用setDateHeader來設定這個頭以避免轉換時間格式的麻煩。

Expires: 應該在什麼時候認為文件已經過期,從而不再快取它?

Last-Modified: 文件的最後改動時間。客戶可以通過If-Modified-Since請求頭提供一個日期,該請求將被為一個條件GET,只有改動時間遲於指定時間的文件才會返回,否則返回一個304(Not Modified)狀態。Last-Modified也可用setDateHeader方法來設定。

Location: 表示客戶應當到哪裡去提取文件。Location通常不是直接設定的,而是通過HttpServletResponse的sendRedirect方法,該方法同時設定狀態程式碼為302。

Server: 伺服器名字。Servlet一般不設定這個值,而是由Web伺服器自己設定。

Set-Cookie : 設定和頁面關聯的Cookie。Servlet不應使用response.setHeader(“Set-Cookie”, …),而是應使用HttpServletResponse提供的專用方法addCookie。參見下文有關Cookie設定的討論。

HTTP狀態碼(HTTP Status Code)

當瀏覽者訪問一個網頁時,瀏覽者的瀏覽器會向網頁所在伺服器發出請求。當瀏覽器接收並顯示網頁前,此網頁所在的伺服器會返回一個包含HTTP狀態碼的資訊頭(server header)用以響應瀏覽器的請求。

HTTP狀態碼分類
HTTP狀態碼由3個十進位制數字組成,第一個十進位制數字定義了狀態碼的型別後兩個數字沒有分類的作用。

HTTP狀態碼共分為5種類型:

分類 類別 分類描述
1** Informational(資訊狀態嗎) 資訊,伺服器收到請求,需要請求者繼續執行操作
2** Success(成功狀態碼) 成功,操作被成功接收並處理
3** Redirection(重定向狀態碼) 重定向,需要進一步的操作以完成請求
4** Client Error(客戶端錯誤狀態碼) 客戶端錯誤,請求包含語法錯誤或無法完成請求
4** Server Error(伺服器狀態碼) 伺服器錯誤,伺服器在處理請求的過程中發生了錯誤

下面是常見的HTTP狀態碼:
200 - 請求成功
301 - 資源(網頁等)被永久轉移到其它URL
404 - 請求的資源(網頁等)不存在
500 - 內部伺服器錯誤