重識TCP/IP協議族與HTTP基礎

不忘初心 砥礪前行, Tomorrow Is Another Day !html

本文概要:git

  1. TCP/IP協議族的網絡分層
    • TCP三次握手四次揮手
  2. Http簡介
  3. 報文結構
  4. Http的請求方法及狀態碼
  5. 經常使用的Header

前言:github

聲明:掌握好HTTP很是重要,具體理由本文最後再揭曉!json

一. TCP/IP協議族的網絡分層

在瞭解HTTP協議以前,先來快速瞭解TCP/IP的網絡分層以及三次握手四次揮手的流程.api

1.1 網絡分層

因爲網絡的不穩定性,因此將網絡分層多個網絡模型.緩存

  • 應用層: HTTP FTP DNS
  • 傳輸層: TCP UDP
  • 網絡層: IP
  • 鏈路層: 以太網 WIFI

大體流程:bash

  1. 應用層將內容打包好交給傳輸層.
  2. 傳輸層負責將內容信息進行切割分包,依次交給網絡層.並確認信息是否發送成功.
    • 若是不成功,將數據包繼續交給網絡層發送.
  3. 網絡層只負責將信息的發送到目標地址,不負責信息所有準確發送到目標地址.
    • 確認信息是否發送成功的是傳輸層.
  4. 最後實際發送的是經過咱們的鏈路層也就是網線和網關路由等.

1.2 TCP三次握手四次揮手

這裏用最簡單粗暴的方式快速瞭解其過程,不帶任何複雜的專業術語.讓你看圖就明白.服務器

  • 三次握手

TCP三次握手
  • 四次揮手

TCP四次揮手

能夠發如今四次揮手中,第2步與第3步會分開發送,之因此這樣是由於此時服務器可能還有消息沒有發送完畢.因此就沒有像握手流程時一塊兒發送消息.網絡

二. Http簡介

HyperText Transfer Protocol 超文本傳輸協議app

  • URL 格式 : 協議類型 + 主機名 + 路徑

示例

api.github.com/users?key1=…

  • http : 協議類型
  • api.github.com : 主機名
  • /users?key1=value1&key2=value2 : 路徑

三. 報文結構

  • 請求報文結構

HTTP請求報文結構

示例

GET /users HTTP/1.1
    Host: api.github.com
    Content-Type: text/html
    Content-Length: 110

    bodybodybody僞裝我是一個Body
    bodybodybodybodybodybody
複製代碼
  • 響應報文結構
    響應報文和請求報文大同小異,只是將請求行換成了狀態行.

響應報文狀態行結構

示例

HTTP/1.1 200 OK
    content-type: application/json; charset=utf-8
    cache-control: public, max-age=60, s-maxage=60
    content-encoding: gzip
    
    bodybodybody僞裝我是一個Body
    bodybodybodybodybodybody
複製代碼

四. 請求方式及狀態碼

4.1 狀態碼
status code 類別 緣由短語 示例
1XX Informational(臨時信息) 接收的請求正在處理 100(繼續發送)
2XX Success 請求正常處理完畢 200(OK)
3XX Redirection(重定向) 須要進行附加操做以完成請求 301(永久移動)、304(內容未改變)
4XX Client Error 服務器沒法處理請求 400(客戶端請求錯誤)、404(內容找不到)
5XX Server Error 服務器處理請求出錯 500(服務器內部錯誤)

更多信息,能夠查看HTTP狀態碼詳解

4.2 請求方式
Method description
GET 1. 獲取資源 2. 不發送Body
POST 1. 增長或者修改資源 2. 發送Body
PUT 1.修改資源 2. 發送Body
DELETE 1.刪除資源 2. 不發送Body
HEAD 與GET基本一致 , 區別在於返回響應無Body

五. 常見的Header

HTTP的元數據,傳遞一些附加信息.

格式: 鍵: 值,注意冒號後面有一個空格

因爲Header過多,這裏只列舉了我的以爲比較重要且經常使用的Header

5.1 通用的Header
字段名 內容說明
Content-Type 內容類型(下一節詳細講解)
Content-Length 內容長度,單位字節
Content-Encoding 壓縮編碼格式,如gzip
Last-Modified 資源的最後修改日期時間
Cache-Control 控制緩存的行爲,取值爲通常爲no-cache或max-age=XX
5.2 請求Header
字段名 內容說明
Host 請求的主機和端口號
User-Agent 用戶代理,僅用於找到目標主機後確認主機域名和端口
Accept 接受的媒體類型,能夠多個值,用,(半角逗號)分開.如text/html,
Accept-Charset 接受的字符集,如UTF-8
Accept-Encoding 接受的壓縮編碼類型,如gzip
--- ------------------------------------------
Last-Modified 值,用於確認某個資源是否被更改過,沒有更改過(304)就從緩存中讀取
If-Modified-Since 比較資源的更新時間;值爲上一次服務器返回的
If-Match 比較實體標記(ETag)
If-None-Match 比較實體標記(與 If-Match 相反);值爲上一次服務器返回的 ETag 值,通常會和If-Modified-Since一塊兒出現
--- ------------------------------------------
Cookie 已有的Cookie
Authorization 用於設置身份認證信息
5.3 響應Header
字段名 內容說明
Location 令客戶端重定向至指定URI
Transfer-Encoding 分塊傳輸,如Transfer-Encoding: chunked
Accept-Range 如Accept-Range: bytes,表示服務器支持按字節獲取數據
Content-Range 如Content-Range:-/total,表示發送的是哪段數據
----------- ------------------------------
ETag 資源的匹配標識,和Last-Modified、If-None-Match、If-Modified-Since配合,用於緩存控制
Set-Cookie 設置Cookie

最後着重學習下Content-Type,這是實際開發中最常用的.

  • Content-Type
    指定Body的類型
  1. text/html 通常用於響應時,返回html頁面.

示例

HTTP/1.1 200 OK
    content-type: text/html; charset=utf-8
    Content-Length: 666
    
    <!DOCTYPE html>
    <html>
    <head>
        ......
    </head>
    <body>
        ......
    <body>    
    </html>

複製代碼
  1. application/x-www-form-urlencoded
    普通表單,提交純文本.

示例

POST /users HTTP/1.1
Host: api.github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 33

userName=jasonhww&password=123456
複製代碼

對應Retrofit代碼

@FormUrlEncoded
@POST("/users")
Observable<User> login(@Field("userName") String userName, @Field("password") String
password);
複製代碼
  1. multipart/form-data; boundary={boundary} 帶文件的表單

將body分紅多個部分,每部分都被boundary分紅單獨的段;

  • 每段以 -- 加 boundary開頭,
  • 而後是該段的conten-disposition,
  • 空行,
  • 傳入的value,
  • 最後請求結束的標識爲boundary後面加--

示例

POST /users/photo HTTP/1.1
           Host: api.github.com
           Content-Length: 3698
請求頭      Content-Type: multipart/form-data;boundary={boundary的值}
空行
請求體part1 --{boundary的值}
            conten-disposition: form-data; name="userName"
            \r\n
            jasonhww
請求體part2 --{boundary的值}
            conten-disposition: form-data; pwd="password"
            \r\n
            123456
請求體part3 --{boundary的值}
            conten-disposition: form-data; name="photo"; filename="文件名.txt";
            Content-Type: image/jpeg
            \r\n
            sdsdsdfqfvfvsvadvavdavakvkakvadvanvnav
            afdfafaiewfre482ekdsji21dnefrgoonwncvewnfefeowkkr假設我是一個文件ddsrrogkrn2n3934
請求體結束  ---boundary的值--

複製代碼

其中Content-Disposition中的filename是區分是否當成文件;由於文件有不一樣的類型,因此還要使用Content-Type指示文件的類型;若是不知道是什麼類型取值能夠爲application/octet-stream表示該文件是個二進制文件.

對應Retrofit代碼

@Multipart
@POST("/users/photo")
Observable<User> uploadPhoto(@Part("userName") RequestBody userName, @Part("password") RequestBody password, @Part("photo")
RequestBody photo);


RequestBody namePart = RequestBody.create(MediaType.parse("text/plain"),
nameStr);
RequestBody pwdPart = RequestBody.create(MediaType.parse("text/plain"),
nameStr);
RequestBody avatarPart = RequestBody.create(MediaType.parse("image/jpeg"),
avatarFile);
api.addUser(namePart, avatarPart);

複製代碼
  1. application/json , image/jpeg
    單內容,實際開發使用較少.

示例-提交json

POST /users HTTP/1.1
Host: api.github.com
Content-Type: application/json
Content-Length: 41

{"userName":"jasonhww","password":123456}
複製代碼

這樣請求body中直接爲json字符串了

對應Retrofit代碼

@POST("/users")
Observable<User> addUser(@Body("user") User user);

複製代碼

示例-提交文件

POST /users/photo HTTP/1.1
Host: api.github.com
Content-Type: image/jpeg
Content-Length: 6666

dsfdsfncwowncnowncodwcw...假設是個文件數據
複製代碼

這樣請求body中直接爲文件數據了

對應Retrofit代碼

@POST("/users/photo")
Observable<User> updatePhoto(@Body RequestBody avatar);
複製代碼

最後順便提下restFul,其實 RestFul風格就是指規範的使用HTTP,可是國內大多數公司通常都不聽從.好比請求方式,實際就只會用到GET與POST.

另外:前面提到掌握好HTTP很是重要,如今揭曉理由,理由就是調試接口時,與後臺互懟的強力保障,不再要擔憂他們忽悠客戶端了.O(∩_∩)O
不過新時代社會主義仍是和諧爲主,儘可能少互懟,合做雙贏纔是正道!

因爲本人技術有限,若有錯誤的地方,麻煩你們給我提出來,本人不勝感激,你們一塊兒學習進步.

參考連接:

相關文章
相關標籤/搜索