三、應用層:HTTP

目錄
一、字符編碼和各個碼錶
二、HTTP
 1、HTTP的數據格式
  1.1 HTTP請求的數據格式 = 請求行 + 請求頭 + 請求體
  1.2 HTTP響應的數據格式 = 響應行 + 響應頭 + 響應體
 2、請求行和響應行
  2.1 HTTP請求的方法
  2.2 HTTP請求的URI
  2.3 HTTP的版本
  2.4 HTTP響應的狀態碼
 3、請求頭和響應頭
  3.1 常見的請求頭字段
  3.2 常見的響應頭字段
 4、請求體和響應體
  4.1 請求體編碼/響應體編碼
  4.2 請求體格式/響應體格式

待補充
2、Cache-Control
3、HTTP版本2.0、3.0的一些內容


一、字符編碼和各個碼錶


首先了解一下字符編碼和各個碼錶,因爲HTTP裏有URL編碼和請求體編碼/響應體編碼這兩個東西要用到編碼的知識。

  • ASCII編碼和ASCII碼錶

計算機起源於美國,它們只能存儲二進制的0和1,也就是說只能存儲數字,那它們是怎麼存儲英文的呢?

美國國家標準局推出了ASCII編碼——用一個特定的數字來代表一個特定的字母,並且強制規定這個數字佔一個字節。這樣字母和數字一一對應的關係就形成了一張表——ASCII碼錶,考慮到實際使用,這張表裏又塞進了阿拉伯數字和英文的標點符號,此外還塞進了一些特殊的控制字符,總之英文模式下鍵盤上能敲出來的東西都直接對應在這張表裏了,總共也就128個。

計算機在存儲英文時,會採用ASCII編碼把一個一個的字符編碼成對應的數字存儲起來。而計算機在顯示英文時,又會把一個字節一個字節的數字解碼成字符顯示出來,因爲在ASCII編碼和ASCII碼錶系統下,一個字符佔一個字節。

  • GB2312編碼和GB2312碼錶

後來世界各地都開始使用計算機,很多國家使用的不是英文,ASCII編碼和ASCII碼錶根本不能滿足他們的需求,比如我們中國就有6000多個常用的漢字,那計算機是怎麼存儲中文的呢?

國家標準局推出了GB2312編碼——也是用一個特定的數字來代表一個特定的漢字,只不過強制規定這個數字佔兩個字節。這樣漢字和數字一一對應的關係就形成了一張表——GB2312碼錶,對於ASCII碼錶裏的字符,保持其原編碼不變,只是將長度由原來的一個字節擴展爲兩個字節,GB2312碼錶可以說是ASCII碼錶的中文擴展集。

計算機在存儲中文時,會採用GB2312編碼把一個一個的漢字編碼成對應的數字存儲起來。而計算機在顯示中文時,又會把兩個字節兩個字節的數字解碼成漢字顯示出來,因爲在GB2312編碼和GB2312碼錶系統下,一個字符佔兩個字節。

  • UTF-8編碼和Unicode碼錶

互聯網發展之初很多國家都有一套自己的編碼和碼錶,你不能識別我,我也不能識別你,你的電腦要想顯示中文文件就得給電腦裝一個“中文編碼和碼錶系統”,你的電腦要還想顯示俄語文件就還得給電腦裝一個“俄語編碼和碼錶系統”等等,一旦裝錯了字符系統,顯示就會出現亂碼,怎麼解決這個問題呢?

國際標準化組織ISO推出了Unicode碼錶——一個包含了世界上所有國家字符的碼錶,同樣地在這個碼錶裏任何一個字符都唯一對應着一個數字,它是一個很龐大的集合,現在的規模可達100多萬。

電腦上只要裝一個Unicode字符系統,無論想顯示那種語言的文件,只要約定好在存儲文件的時候存儲成特定編碼方式的文件就好了,其它電腦就能正常解碼並顯示。

但需要注意的是,Unicode碼錶只強制規定了哪個數字代表哪個字符,卻沒有強制規定這個數字佔幾個字節(上面ASCII碼錶和GB2312碼錶不僅強制規定了哪個數字代表哪個字符,而且還強制規定了這個數字佔一個字節或者兩個字節),這是因爲Unicode碼錶過於龐大,很多排在後面的字符需要用三個字節的數字才能代表,那如果Unicode碼錶強制規定這個數字佔三個字節,這勢必會造成存儲空間的極大浪費,比如一個英文字母本來只需要一個字節就能存儲得下了,現在卻要在前面兩個字節裏全部填0,文本文件也因此大出兩三倍。於是就衍生出了針對Unicode碼錶的衆多編碼方式:UTF-8編碼、UTF-16編碼(兩個字節或四個字節)、UTF-32編碼(四個字節)等來規定這個數字佔幾個字節。其中UTF-8編碼是目前使用最廣泛的,它最大的特點就是可變長編碼,會根據不同的情況用不同字節的數字來代表字符,比如當遇到英文字母時就還是一個字節、和ASCII碼錶一模一樣,當遇到中文漢字時就是三個字節等等。因此在UTF-8編碼和Unicode碼錶系統下,一個字符佔幾個字節是不固定的,一個字母佔一個字節,一個漢字佔三個字節,但“具體佔幾個字節”這個信息也會被編碼存儲在這個數字裏,以便後續解碼時能知道到底應該把幾個字節的數據連續在一起解碼。


二、HTTP


HTTP(Hyper Text Transfer Protocol),超文本傳輸協議,是互聯網中應用最廣泛的應用層協議之一。設計HTTP最初的目的就是用來傳輸HTML文本的、就是爲了能讓用戶瀏覽網頁(比如瀏覽器發送一個HTTP請求,服務器就返回一串HTML文本,然後瀏覽器把HTML文本解析、渲染成一個網頁展示給用戶),只不過後來HTTP能傳輸的數據類型非常廣泛了(比如還能傳輸圖片、音頻、視頻等),不僅僅是HTML文本。

HTML(Hyper Text Markup Language),超文本標記語言,用來編寫網頁。所謂超文本是指HTML文本能表達超出文本之外的內容(比如<a href="test.html">點擊跳轉到測試頁面</a>這個HTML文本,它除了能表達“點擊跳轉到測試頁面”這個普通字符串文本之外,它還表達了這是個超鏈接、可以點擊跳轉到測試頁面);所謂標記語言是指HTML文本是由一個一個的標籤(比如<head><body>等)組成的。

1、HTTP的數據格式

我本地服務器上有一串HTML文本如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <form action="/hw/login" method="post">
        <div>Username:<input name="username"></div>
        <div>Password:<input name="password"></div>
        <button type="submit">Login</button>
    </form>
</body>
</html>

可以通過URLhttp://localhost:8080/hw/html/login.html請求到,瀏覽器加載出來的效果如下:

現在我們就在瀏覽器裏請求一下這個URL,並用Wireshark抓一下數據看看。

選中HTTP請求或者HTTP響應,右鍵選擇追蹤流,再選擇追蹤HTTP流,就能看到這一次HTTP請求和HTTP響應的數據了。

雙擊HTTP請求和HTTP響應,更是可以看到這一次HTTP請求和HTTP響應的二進制流(任何數據最終都是轉換成二進制的0和1進行存儲和傳輸的)。

1.1 HTTP請求的數據格式 = 請求行 + 請求頭 + 請求體
  • 請求行:是由HTTP請求的方法、HTTP請求的URI和HTTP的版本組成的;
  • 請求頭:是由一堆請求頭字段組成的;
  • 請求體:就是客戶端傳給服務器的一堆入參,GET請求沒有請求體,POST請求有請求體。

我們拿上面例子中HTTP請求的數據來套一下看看對不對:

  • 請求行:HTTP請求的方法爲GET;然後是一個空格;然後是HTTP請求的URI;然後又是一個空格;然後是HTTP的版本爲1.1;然後是一個回車換行;
  • 請求頭:接下來就是一對一對的請求頭key-value,請求頭字段名、冒號、一個空格、請求頭字段值、回車換行;(注意:所有的請求頭字段結束後有一個回車換行)
  • 請求體:因爲上面例子用的是GET請求,所以沒有請求體,後面會舉POST請求的例子,到時可留意一下請求體。

補充:回車換行

回車符(return):它的本意是回到當前行的開頭。
換行符(newline):它的本意是下移一行。

Windows系統保留了最原始的做法,每行的結尾都會有一個回車符 + 一個換行符,文本編輯器只要見到這兩個字符就會先回到當前行的開頭、然後再下移一行顯示,也就是我們口頭上常說的換行。但是爲了節省內存,Mac系統設計一個回車符的功能就相當於Windows系統一個回車符 + 一個換行符的功能,所以Mac系統每行的結尾只有一個回車符,文本編輯器只要見到回車符就換行;同理Unix系統每行的結尾只有一個換行符,文本編輯器只要見到換行符就換行。爲了兼容各個系統,HTTP要求使用最原始的做法一個回車符 + 一個換行符來代表換行。

1.2 HTTP響應的數據格式 = 響應行 + 響應頭 + 響應體
  • 響應行:是由HTTP的版本和HTTP響應的狀態碼組成的;
  • 響應頭:是由一堆響應頭字段組成的;
  • 響應體:就是服務器發送給客戶端的數據。

同樣我們拿上面例子中HTTP響應的數據來套一下看看對不對:

  • 響應行:HTTP的版本爲1.1;然後是一個空格;然後是HTTP響應的狀態碼200;然後是一個回車換行。(短語是可選的)
  • 響應頭:接下來就是一對一對的響應頭key-value,響應頭字段名、冒號、一個空格、響應頭字段值、回車換行。(注意:所有的響應頭字段結束後有一個回車換行)
  • 響應體:可見響應體就是我們本地服務器上那一串HTML文本。

2、請求行和響應行

2.1 HTTP請求的方法

HTTP請求的方法一共有九個:

  • GET:GET請求一般用來查服務器的數據;GET請求沒有請求體,傳給服務器的一堆入參一般放在URL裏,但是瀏覽器和服務器對URL的長度有限制,所以GET請求不能傳輸太多的數據,注意不是HTTP協議本身對URL的長度有限制。

  • POST:POST請求一般用來增、刪、改服務器的數據;POST有請求體,傳給服務器的一堆入參一般放在請求體裏,無長度限制。

  • HEAD:發送一個HEAD請求就相當於發送了一個GET請求,只不過服務器返回來的數據只有響應行 + 響應頭,沒有響應體而已。(使用場景舉例:在下載一個大文件之前,可以先發送一個HEAD請求,從響應頭裏獲取到文件的大小,再決定是否下載,這樣可以省流量。要是直接發送GET請求的話,服務器就是直接給我們傳輸數據、就是直接下載了)

  • PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH:不常用。

2.2 HTTP請求的URI
2.2.1 URI和URL

URI(Uniform Resource Identifier),統一資源標識符,用於唯一標識一個資源。比如/hw/html/login.html可以唯一標識我本地服務器上的一個HTML資源,它就是一個URI,但是別人也可能使用/hw/html/login.html來唯一標識他們服務器上的一個HTML資源。

URL(Uniform Resource Locator),統一資源定位符,用於唯一定位一個資源。比如http://localhost:8080/hw/html/login.html可以唯一定位我本地服務器上的一個HTML資源,它就是一個URL,我們可以通過URL直接找到某個資源。

因爲URL能唯一定位一個資源,所以它肯定也能唯一標識一個資源,因此所有的URL都是URI,但並非所有的URI都是URL,即URL是URI的子集。URI和URL的主要區別就是URL是全網唯一的,我們可以通過URL直接找到某個資源,而非URL的URI不是全網唯一的,它必須得配合協議、IP地址、端口號才能找到某個資源。

2.2.2 URL編碼

國際標準化組織ISO強制規定URL裏只能出現:

  • 英文字母A ~ Za ~ z
  • 阿拉伯數字0 ~ 9
  • 部分英文的標點符號$-_.+!*'()
  • 還有一些有特殊用途的保留字符。

其它任何字符都必須編碼後才能出現在URL裏;此外,如果保留字符作爲參數的值,那它們也必須編碼後才能出現在URL裏。

保留字符 特殊用途
: 1、用來聯合//表示一個協議,如http://https://
2、用來分隔IP地址和端口號,如127.0.0.1:8080
/ 1、用來聯合:表示一個協議,如http://https://
2、用來分隔路徑,如/hw/html/login.html
. 1、用在IP地址裏,如127.0.0.1
2、用在路徑裏,如login.html
? 用來分隔實際的URL和參數
& 用來分隔參數
= 用來指定參數的值
% 用來標識是一個編碼後的字符
#;,@ 保留

我們客戶端開發人員可以採用任意編碼方式對URL編碼,比如ASCII編碼、GB2312編碼等,但是如果決定採用這些編碼方式,就必須先跟服務端開發人員約定好,以便他們能夠正確對URL解碼。

但是實際開發中我們很少寫對URL編碼的代碼,這是因爲實際的URL(比如http://localhost:8080/hw/html/login)都被服務端開發人員規範成了合法字符;而GET請求傳給服務器的一堆入參(比如username=123&password=4 5%6)是放在URL裏,雖說有可能出現非法字符,但是它們也都被網絡三方庫內部默認採用UTF-8編碼給編碼掉了;而POST請求傳給服務器的一堆入參是放在請求體裏,談不到URL編碼了。

那雖然我們客戶端這邊的網絡三方庫內部針對URL默認採用UTF-8編碼,但服務端開發人員那邊知道嗎?他們接收到URL後萬一用別的方式解碼呢?實際開發中我們也很少跟服務端開發人員約定說“我們都採用UTF-8編碼”啊,這是因爲服務端那邊的網絡三方庫內部也默認採用UTF-8編碼來對URL解碼。也就是說,現在客戶端和服務端的網絡三方庫內部針對URL默認都採用UTF-8編碼,大家都默認了......如果真得決定採用別的編碼方式,那就去約定吧。

採用UTF-8編碼對URL編碼的格式爲:一個%,後面加上該字符在Unicode碼錶裏對應的十六進制數字。比如我們用AFNetworking或者Dio發起一個GET請求http://localhost:8080/hw/login?username=123&password=4 5%6,其實這個GET請求真正上是http://localhost:8080/hw/login?username=123&password=4%205%256,空格" "會被編碼成%20%會被編碼成%25

2.3 HTTP的版本
  • 1991年發佈了HTTP/0.9

1、只支持GET請求
2、只支持傳輸HTML文本

  • 1996年發佈了HTTP/1.0

1、新增支持POST請求等
2、新增支持傳輸圖片、音頻、視頻等
3、瀏覽器每發送一個HTTP請求,都要與服務器建立TCP連接,數據傳輸完成後立即斷開TCP連接

比如我們在瀏覽器裏訪問一下http://baidu.com,瀏覽器就會與服務器建立TCP連接,服務器會返回一串HTML文本,瀏覽器收到後就會斷開TCP連接。

但是當瀏覽器解析HTML文本的時候,會發現HTML文本里引用了很多其它的資源:CSS、JS、圖片等,此時瀏覽器就會針對每一個資源都發起一個HTTP請求去服務器獲取,而每發起一個HTTP請求都意味着一次建立TCP連接和一次斷開TCP連接。

  • 1997年發佈了HTTP/1.1(最經典、使用最廣泛的版本)

採用長連接(Connection: keep-alive),多個HTTP請求共用同一個TCP連接

比如我們在瀏覽器裏訪問一下http://baidu.com,瀏覽器就會與服務器建立TCP連接,服務器會返回一串HTML文本,但是瀏覽器收到後不會斷開TCP連接。

當瀏覽器解析HTML文本的時候,會發現HTML文本里引用了很多其它的資源:CSS、JS、圖片等,此時瀏覽器就會針對每一個資源都發起一個HTTP請求去服務器獲取,但是這些HTTP請求都共用的是剛纔創建的那個TCP連接。那這個TCP連接什麼時候斷開?其實這個長連接有個超時時間,等傳輸完數據,然後再過超時時間這麼長時間,這個TCP連接就會斷開。

  • 2015年發佈了HTTP/2.0
  • 2018年發佈了HTTP/3.0
2.4 HTTP響應的狀態碼

HTTP響應的狀態碼一共有五類:

  • 100 ~ 199:信息響應
  • 200 ~ 299:成功響應
  • 300 ~ 399:重定向響應
  • 400 ~ 499:客戶端錯誤響應
  • 500 ~ 599:服務器錯誤響應

常見HTTP響應的狀態碼:

  • 200 OK:請求成功
  • 400 Bad Request:服務器無法理解該請求(情況一:HTTP請求的數據格式真得有問題,那服務器就會自動給客戶端返回400的響應,根本到不了服務端開發人員這一步。情況二:HTTP請求的數據格式沒問題,到了服務端開發人員這一步,發現客戶端少傳參數了,比如要求客戶端傳name和age兩個參數,結果客戶端只傳了name一個參數,那服務端開發人員就可能會給客戶端返回400的響應)
  • 404 Not Found:服務器無法找到請求的資源(一般是HTTP請求的URL拼錯了)
  • 405 Method Not Allowed:服務器禁止了使用當前方法的HTTP請求(一般是HTTP請求的方法用錯了,比如服務器要求某個HTTP請求必須用POST,客戶端卻用了GET)
  • 500 Internal Server Error:服務器崩了(一般是服務端開發人員的代碼寫的有問題)

3、請求頭和響應頭

3.1 常見的請求頭字段

實際開發中我們很少寫設置請求頭的代碼,這是因爲很多事情都被網絡三方庫內部幫我們給做了,比如設置Host、User-Agent、Connection、Content-Type、Content-Length等,我們只需要調用API發起網絡請求就可以了。當然有些情況下我們也可能需求去寫設置請求頭的代碼,比如設置Accept、Accept-Charset,或者斷點續傳設置Range,或者設置緩存Cookie、Cache-Control等。此外除了標準的請求頭,我們還可以自定義請求頭字段塞到請求頭裏。

  • Host:客戶端指定自己想訪問的服務器的IP地址和端口號,比如Host: localhost:8080
  • User-Agent:客戶端表明自己的身份,使得服務器能夠識別用戶使用的設備、操作系統及版本、CPU 類型等,比如Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.3 Safari/605.1.15
  • Accept:客戶端告訴服務器客戶端能接收什麼格式的響應體,比如Accept: text/plain,text/html,text/css;q=0.9,text/javascript;q=0.9,application/json;charset=UTF-8,image/png,image/jpeg,*/*;q=0.8;(q代表優先級,默認值、最大值爲1,值越大代表優先級越高,即建議服務器優先考慮給我傳輸這種格式以及這種編碼的響應體)
  • Accept-Charset:客戶端告訴服務器客戶端能接收什麼編碼方式比如:Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7;(*代表任意)
  • Connection:客戶端告訴服務器使用長連接,比如Connection: keep-alive;(HTTP/1.1下,即便沒有這個請求頭,也默認使用長連接)
  • Content-Type(只針對POST請求):客戶端告訴服務器發送給服務器的是什麼格式以及採用了什麼編碼方式的請求體,比如Content-Type: application/x-www-form-urlencoded
  • Content-Length(針對POST請求):客戶端告訴服務器發送給服務器的請求體有多長(單位爲字節),比如Content-Length: 43
  • Range:客戶端告訴服務器我想拿你那部分的數據,多線程斷點續傳經常用,比如Range: bytes=500-999
  • Cookie:Cookie和token/ticket的作用是一樣的。比如我們App裏的某些接口必須得用戶登錄後才能訪問,那如果用戶不登錄、直接通過瀏覽器去訪問這些接口,服務端就會返回錯誤信息,這是對的就應該這樣。而如果用戶通過App的登錄接口成功登錄,此時服務器針對登錄接口的響應裏就會通過響應頭裏的Set-Cookie: JSESSIONID=666把一個唯一的標識JSESSIONID=666返回給客戶端(服務端的網絡三方庫幫他們做了這件事),客戶端會保存下來,後續用戶在App裏訪問其它所有的接口時都會通過請求頭裏的Cookie字段把Cookie: JSESSIONID=666傳給服務端(客戶端的網絡三方庫幫我們做了這件事),服務端在收到來自客戶端的請求時,如果發現請求頭裏有Cookie字段並且JSESSIONID的值能跟服務端存儲的對上號,就判定爲這個用戶登錄過,就允許訪問那些必須登錄後才能訪問的接口,當然Cookie也是有有效時間的,這個服務端可以控制。只不過實際開發中我們沒通過請求頭和響應頭的Cookie來做這件事,而是自己寫了一套token/ticket作爲接口的參數傳來傳去,但是他們的作用是一樣的。
  • Cache-Control:以後專門說。
3.2 常見的響應頭字段
  • Connection:服務器告訴客戶端使用或者斷開長連接,比如Connection: keep-alive或者Connection: close
  • Keep-Alive:服務器告訴客戶端長連接會保持多長時間(單位爲秒),比如Keep-Alive: timeout=20;(注意:網絡三方庫設置的超時時間是指到了那個時間點連TCP連接都沒建立好,而不是指數據獲取不完而超時,只要在超時時間內建立好了TCP連接,這個超時時間就沒有意義了,那麼即便你的數據要一個小時才能獲取完也不會超時。網絡三方庫的超時時間跟這裏長連接的超時時間沒有半點兒關係,這裏的超時時間第一個前提就是TCP連接已經成功建立、此時三方庫的超時時間已經失去意義,這裏的超時時間是指TCP建立好、數據傳輸也傳輸完了、TCP連接仍然會保持多長時間)
  • Content-Type:服務器告訴客戶端發送給客戶端的是什麼格式以及採用了什麼編碼方式的響應體,比如Content-Type: application/x-www-form-urlencoded
  • Content-Length:服務器告訴客戶端發送給客戶端的響應體有多長(單位爲字節),比如Content-Length: 43
  • Accept-Range:服務器告訴客戶端是否支持客戶端獲取部分數據,比如Accept-Range: bytes代表支持,Accept-Range: none代表不支持;
  • Set-Cookie:跟請求頭裏的Cookie連用,詳見”常見的請求頭字段“部分;
  • Cache-Control:以後專門說。

4、請求體和響應體

4.1 請求體編碼/響應體編碼

國際標準化組織ISO強制規定Body裏也只能出現跟URL要求一樣的合法字符,非法字符都必須編碼後才能出現在Body裏。Body編碼就不多說了,實際開發中我們很少去寫Body編碼的代碼,這是因爲現在客戶端和服務端的網絡三方庫針對Body默認也都採用UTF-8編碼,大家都默認了......如果真得決定採用別的編碼方式,那就去約定吧。

4.2 請求體格式/響應體格式

實際開發中當我們使用POST請求的時候,要考慮一個問題,那就是”要採用什麼格式把請求體發送給服務端“,常用的有三種格式:表單提交(請求頭裏對應的應該寫Content-Type: application/x-www-form-urlencoded,AFNetworking默認)、JSON提交(請求頭裏對應的應該寫Content-Type: application/json,Dio默認)和multipart提交(請求頭裏對應的應該寫Content-Type: multipart/form-data; boundary=...,上傳文件時必須採用這種格式),好在網絡三方庫已經幫我們把設置請求頭、組裝請求體格式這些非常非常繁瑣的事情給做了,我們需要做的就是跟後臺約定好要採用什麼格式上傳、然後調用網絡三方庫相應的API、把要傳給服務端的入參以Map的形式扔給網絡三方庫就好了,比如當我們調用表單提交的API時,三方庫就會在請求頭裏設置Content-Type: application/x-www-form-urlencoded,然後把入參組裝成表單提交特有的格式,其它兩種也是同理。不過可能你會發現實際開發中我們即便是在使用POST請求,但也很少去跟服務端開發人員對接到底要使用哪種格式,這是因爲大家已經默認提交普通數據時採用表單提交,上傳文件時採用multipart提交,響應體採用JSON提交返回,而一旦服務端真有哪個接口要求採用JSON提交、可是雙方又沒有提前對接、客戶端繼續採用了默認的表單提交,那這個POST請求就會報錯,因爲客戶端發給服務器的數據他們解析不了,大家就一塊兒去調試吧,最終會發現原來是提交格式不對。

而使用GET請求的時候,就不需要考慮什麼表單提交、JSON提交和multipart提交這些東西,因爲它們三個是用來控制請求體的格式的,GET請求根本就沒有請求體啊。也許你會考慮一下GET請求的URL是否編碼了,但實際上也不用過慮,因爲網絡三方庫肯定會幫我們做URL編碼。

下面就舉例子看一下采用表單提交、JSON提交和multipart提交對請求體格式的影響究竟是什麼,響應體的格式也是同理的,就不貼AFNetworking和Dio的源碼了,以後專門分析源碼的時候再說。

  • 表單提交,請求體的格式爲:

&分割請求參數,用=來分割請求參數名和請求參數值。

  • JSON提交,請求體的格式爲:

{key1: value1, key2: value2}這樣key-value鍵值對的形式。

  • mutipart提交,請求體的格式爲:

--boundary
附加信息 參數名1

參數值1
--boundary
附加信息 參數名2

參數值2
--boundary--

例子:

參考:

1、字符編碼:字符編碼筆記:ASCII,Unicode 和 UTF-8
2、各個碼錶的演變:Unicode 和 UTF-8 有什麼區別?
3、URL編碼:URL編碼
4、URL裏的保留字符:保留字符
5、關於URL的長度限制:關於 HTTP GET/POST 請求參數長度最大值的一個理解誤區
6、頭部字段:HTTP請求頭與響應頭
7、Content-Type:Content-Type 詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章