看看這篇5000字的文章,帶你看不一樣的Android-Http

1.Http的簡介

1.1 Http的含義

HTTP 全稱是 HyperText Transfer Protocal 即超文本傳輸協議。Http是一種基於TCP/IP協議的一種傳輸協議。我們知道OSI模型把網絡通信的工作分為7層,分別是:是物理層、數據鏈路層、網路層、傳輸層、話路層、表示層和應用層。而Http協議是應用層協議。當你上網瀏覽網頁的時候,瀏覽器和 web 服務器之間就會通過 HTTP 在 Internet 上進行數據的發送和接收。HTTP是一個基於請求/響應模式的、無狀態的協議,即我們通常所說的 Request/Response。補充:HTTP,UDP都是無狀態協議,而TCP,FTP是有狀態協議,關於什麼是無狀態協議可以簡單理解為:請求都是獨立的,一次Request對應一次Response。兩次相鄰的請求沒有直接聯繫。但開發中的實際情況通常是,在 http 協議的基礎上,web 應用引入 cookies,session,application 來保持 web 應用之間的狀態。

1.2 Http的特點

  • 支持客戶端/服務器模式
  • 簡單快速:客戶向服務器請求服務時,只需傳送請求方法和路徑。由於 HTTP 協議簡單,使得 HTTP 服務器的程序規模小,因而通信速度很快
  • 靈活:HTTP 允許傳輸任意類型的數據對象。正在傳輸的類型由 Content-Type 加以標記
  • 無連接:無連接的含義是限制每次鏈接只處理一個請求。服務器處理完哭護的請求,並收到客戶的應答後,即斷開鏈接,採用這種方式可以節省傳輸時間
  • 無狀態:HTTP 協議是無狀態協議。無狀態是指協議對於事物處理沒有記憶能力。缺少狀態意味著如果後續處理需要前面的信息,則它必須重傳,這樣可能會導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就較快

1.3 網絡協議四層?

參考:https://blog.csdn.net/cc1949/article/details/79063439我們剛才說了OSI模型把網絡通信的工作分為7層,但實際應用中還是TCP/IP的四層結構,4層是指TCP/IP四層模型,主要包括:應用層、運輸層、網際層和網絡接口層。4層協議和對應的標準7層協議的關係如下圖:

看看這篇5000字的文章,帶你看不一樣的Android-Http

我們來一張經典的4層結構圖說明一下:

看看這篇5000字的文章,帶你看不一樣的Android-Http

那我們就參考上圖分別說一下與HTTP協議密切相關的協議:

1.3.1 傳輸層的TCP(確保可靠性的協議)

TCP 位於傳輸層,提供可靠的字節流服務。所謂的字節流服務( Byte Stream Service )是指,為了方便傳輸,將大塊數據分割成以報文段( segment )為單位的數據包進行管理。而可靠的傳輸服務是指,能夠把數據準確可靠地傳給對方.這裡還要著重講解一下TCP連接的3次握手

為了準確無誤地將數據送達目標處, TCP 協議採用了三次握手( three-way handshaking )策略。握手過程中使用了 TCP 的標誌( flag ) —— SYN ( synchronize ) 和ACK ( acknowledgement )。發送端首先發送個帶 SYN 標誌的數據包給對方。接收端收到後,回傳一個帶有 SYN/ACK 標誌的數據包以示傳達確認信息。最後,發送端再回傳一個帶 ACK 標誌的數據包,代表 “ 握手 ” 結束。若在握手過程中某個階段莫名中斷, TCP 協議會再次以相同的順序發送相同的數據包。如圖所示:

從圖中可以看出,建立連接經歷了三次握手,當數據傳輸完畢,需要斷開連接,而斷開連接經歷了四次揮手:

  • 第一次揮手:主機1(可以是客戶端或服務器),設置seq和ack向主機2發送一個FIN報文段,此時主機1進入FIN_WAIT_1狀態,表示沒有數據要發送給主機2了
  • 第二次揮手:主機2收到主機1的FIN報文段,向主機1回應一個ACK報文段,表示同意關閉請求,主機1進入FIN_WAIT_2狀態。
  • 第三次揮手:主機2向主機1發送FIN報文段,請求關閉連接,主機2進入LAST_ACK狀態。
  • 第四次揮手:主機1收到主機2的FIN報文段,想主機2回應ACK報文段,然後主機1進入TIME_WAIT狀態;主機2收到主機1的ACK報文段後,關閉連接。此時主機1等待主機2一段時間後,沒有收到回覆,證明主機2已經正常關閉,主機1頁關閉連接

1.3.2 網絡層的IP

IP 協議的作用是把各種數據包傳送給對方。而要保證確實傳送到對方那裡,則需要滿足各類條件。其中兩個重要的條件是 IP 地址和 MAC地址( Media Access Control Address )。IP 地址指明瞭節點被分配到的地址, MAC 地址是指網卡所屬的固定地址。 IP 地址可以和 MAC 地址進行配對。 IP 地址可變換,但 MAC地址基本上不會更改。IP使用 ARP 協議憑藉 MAC 地址進行通信

1.3.3 Http工作流程

參考:https://mp.weixin.qq.com/s/7sX3AY7gJomJ2ZEErUqmKA第一步:地址解析,從url中解析協議名稱,主機名,端口號和對應的頁面地址。

第二步:封裝http的請求數據包:這一步主要是封裝自己的信息,比如在post請求時,我們會塞進一個data數據。

第三步:封裝tcp包,建立連接:因為是基於tcp的協議,網絡連接是tcp來完成的,必然要封裝成tcp包,然後tcp再做自己工作,比如封裝ip包,一層層往下傳。

第四步:發送請求:數據整好了,連接也完事了,那就發送action了。

第五步:服務端響應:接受到請求,然後給出響應。

第六步:服務端關閉tcp的連接:一次通信完成之後,若conection的設置不是keep-live的話,服務端會自動關閉tcp的連接。

2.URL詳解

3.1 URL含義

URL(Uniform Resource Locator)是統一資源定位符的簡稱,有時候也被俗稱為網頁地址(網址),是因特網上標準的資源的地址。

3.2 URL構成

URL構成的通用格式為:schema://host[:port#]/path/…/[?query-string][#anchor]我們來分析各部分的含義:

名稱功能schema訪問服務器以獲取資源時要使用哪種協議,比如,http,https 和 FTP 等hostHTTP 服務器的 IP 地址或域名,IP地址是一個最原始的東西,必須通過IP地址才可以找到其他的計算機;而域名只是為了人們記的方便,給出的一個名字。域名的IP地址綁定了以後,當別人訪問這個域名的時候就可以通過DNS解析成IP,再進行訪問。portHTTP 服務器的默認端口是 80,這種情況下端口號可以省略,如果使用了別的端口,必須指明,例如http://www.cnblogs.com:8080path訪問資源的路徑query-string發給 http 服務器的數據 ,比如參數#anchor錨,什麼是錨呢?比如:http://www.aspxfans.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name這個鏈接,錨部分就是從“#”開始到最後。本例中的錨部分是“name”。錨不是一個URL必須的部分 。默認情況下,Google的網絡蜘蛛忽視URL的#部分。但是,如果你希望Ajax生成的內容被瀏覽引擎讀取,那麼URL中可以使用"#!",這裡我們不過多解釋

用事實說話,比如:http://www.mywebsite.com/sj/test/test.aspx?name=sviergn&x=true#stuff其中

名稱對應的字段Schemahttphostwww.mywebsite.compath/js/test/test.aspxQuery-stringname=sviergn&x=trueanchorstuff

再來張比較直觀的圖

看看這篇5000字的文章,帶你看不一樣的Android-Http

3.Http 詳解

3.1 Http請求詳解

HTTP 的請求報文分為三個部分:請求行、請求頭、請求體

3.1.1請求行

請求行(Request line)分為三個部分:請求方法、請求地址和協議版本所以請求行的格式一般是:

看看這篇5000字的文章,帶你看不一樣的Android-Http

舉例:GET /app/appUserAction!getUserLogin.do.html HTTP/1.1

請求地址就是我們要請求服務器的地址,協議版本是我們Http的版本比如:Http1.0、Http1.1等版本。我們主要來說一下請求方法:HTTP/1.1 協議中共定義了八種方法(也叫“動作”)來以不同的方式操作指定的資源.

方法名功能GET向指定的資源發出“顯示”請求,使用 GET 方法應該只用在讀取數據上,而不應該用於產生“副作用”的操作中POST指定資源提交數據,請求服務器進行處理(例如提交表單或者上傳文件)。數據被包含在請求文本中。這個請求可能會創建新的資源或者修改現有資源,或兩者皆有。PUT向指定資源位置上傳其最新內容DELETE請求服務器刪除 Request-URI 所標識的資源OPTIONS使服務器傳回該資源所支持的所有HTTP請求方法。

用*來代替資源名稱,向 Web 服務器發送 OPTIONS 請求,可以測試服務器功能是否正常運作HEAD與 GET 方法一樣,都是向服務器發出指定資源的請求,只不過服務器將不傳回資源的本文部分,它的好處在於,使用這個方法可以在不必傳輸全部內容的情況下,就可以獲取其中關於該資源的信息(原信息或稱元數據)TRACE顯示服務器收到的請求,主要用於測試或診斷CONNECTHTTP/1.1 中預留給能夠將連接改為通道方式的代理服務器。通常用於 SSL 加密服務器的鏈接(經由非加密的 HTTP 代理服務器)

其中,最常見的是 GET 和 POST 方法,如果是 RESful 接口的話一般會用到 PUT、DELETE、GET、POST(分別對應增刪查改)補充:

RESful 是一種軟件架構風格、設計風格,而不是標準,只是提供了一組設計原則和約束條件。它主要用於客戶端和服務器交互類的軟件。基於這個風格設計的軟件可以更簡潔,更有層次,更易於實現緩存等機制。

3.1.2

請求頭請求頭可用於傳遞一些附加信息,格式為:鍵: 值,注意冒號後面有一個空格:如圖,是Fiddler抓包獲取的請求頭信息:

<code>GET省略包含參數的請求......... HTTP/1.1
Host: 省略.........
Connection: keep-alive
User-Agent: Mozilla/5.0 (Linux; U; Android 9; zh-cn; DUK-AL20 Build/HUAWEIDUK-AL20) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/9.0 Mobile Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,image/sharpp,image/apng,image/tpg,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh-CN;q=0.8,en-GB;q=0.6,en-US;q=0.4

/<code>

這個請求頭信息並不能代表所有請求頭信息,所以我們來說一說請求頭的一些知識點:首先,請求頭通常用來傳遞一些附加信息,格式為:鍵: 值,注意冒號後面有一個空格:請求和響應常見通用的 Header

名稱作用Content-Type請求體/響應體的類型,如:text/plain、application/jsonAccept說明接收的類型,可以多個值,用,(英文逗號)分開Content-length請求體/響應體的長度,單位字節Content-Encoding請求體/響應體的編碼格式,如 gzip、deflateAccept-Encoding告知對方我方接受的 Content-EncodingETag給當前資源的標識,和Last-Modified、If-None-Match、If-Modified-Since配合,用於緩存控制Cache-Control取值一般為no-cache、max-age=xx,xx為整數,表示資源緩存有效期(秒)

請求Header內包含常用信息如下:

名稱作用Authorization用於設置身份認證信息User-Agent用戶標識,如:OS 和瀏覽器的類型和版本If-Modified-Since值為上一次服務器返回的Last-Modified值,用於確定某個資源是否被更改過,沒有更改過就從緩存中讀取If-None-Match值為上一次服務器返回的 ETag 值Cookie已有的CookieReferer標識請求引用自哪個地址,比如你從頁面 A 跳轉到頁面 B 時,值為頁面 A 的地址Host請求的主機和端口號

3.1.3 請求體

請求體(又叫請求正文)是 post 請求方式中的請求參數,以 key = value 形式進行存儲,多個請求參數之間用&連接,如果請求當中請求體,那麼在請求頭當中的 Content-Length 屬性記錄的就是該請求體的長度,就是我們通常訪問服務器需要傳的參數信息,如:http://www.baidu.com/login.do?account=123456&password=99fe158e8abc9ffbd09eab0ec9d81781根據應用場景的不同,HTTP 請求的請求體有三種不同的形式第一種:移動開發者常見的,請求體是任意類型的,服務器不會解析請求體,請求體的處理需要自己解析,如圖:

看看這篇5000字的文章,帶你看不一樣的Android-Http

第二種:第二種和第三種都有固定的格式,是服務器端開發人員最先了解的兩種。這裡的格式要求就是 URL 中 Query String(可以理解為參數) 的格式要求:多個鍵值對之間用&連接,鍵與值之間用=連接,且只能用 ASCII 字符,非 ASCII 字符需使用UrlEncode編碼。

看看這篇5000字的文章,帶你看不一樣的Android-Http

第三種:第三種請求體被分成多個部分,文件上傳 時會被使用,這種格式最先是被用於郵件傳輸中,每個字段/文件都被 boundary(Content-Type中指定的)分成單獨的段,每段以--加 boundary 開頭,然後是該段的描述頭,描述頭之後空一行接內容,請求結束的標識為 boundary 後面加--

看看這篇5000字的文章,帶你看不一樣的Android-Http

3.2 Http響應詳解

HTTP 響應的格式上除狀態行(第一行)與請求報文的請求行不一樣之外,其他的就格式而言是一樣的。Http響應主藥由三部分:響應狀態行、響應頭、響應體.3.2.1 響應狀態行Http的響應狀態行格式如下:

看看這篇5000字的文章,帶你看不一樣的Android-Http

舉例:HTTP/1.1 200 OK那我們說一下常見響應碼的含義:

狀態碼對應信息1xx提示信息—表示請求已接收,繼續處理2xx用於表示請求已被成功接收、理解、接收3xx用於表示資源(網頁等)被永久轉移到其它 URL,也就是所謂的重定向4xx客戶端錯誤—請求有語法錯誤或者請求無法實現5xx務器端錯誤—服務器未能實現合法的請求

3.2.2 響應頭

響應頭同樣可用於傳遞一些附加信息,

<code>注:只是部分信息。
Server: nginx/1.12.2
Date: Wed, 30 Jan 2019 02:06:41 GMT
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: JSESSIONID=96C4243B3715D585A3699BF9451D5FE3; Path=/; HttpOnly
Content-Language: zh-CN

/<code>

常見的響應Header

名稱作用Date服務器的日期Last-Modified該資源最後被修改的時間Transfer-Encoding取值一般為 chunked,出現在 Content-Length 不能確定的情況下,表示服務器不知道響應板體的數據大小,一般同時出現Content-Encoding響應頭Set-Cookie設置 CookieLocation重定向到另一個 URL,如輸入瀏覽器就輸入 baidu.com 回車,會自動跳轉到https://www.baidu.com 就是通過這個響應頭控制的Server後臺服務器

3.2.3 響應體

響應體也就是網頁的正文內容,一般在響應頭中會用 Content-Length 來明確響應體的長度,便於瀏覽器接收,對於大數據量的正文信息,也會使用 chunked 的編碼方式。


分享到:


相關文章: