常用物聯網應用層協議(1)——先說HTTP協議
阿新 • • 發佈:2020-10-27
# 概念
## 簡介
HTTP是一個屬於應用層的面向物件的協議,目前使用最為廣泛的是HTTP1.1協議。當然,許多網站已經開始支援HTTP2.0,HTTP2複雜度高於HTTP1.1,我們先從HTTP1.1說起。
HTTP於1990 年提出,經過幾年的使用與發展,得到不斷地完善和擴充套件。主要有以下特點:
* 支援客戶/伺服器模式
* ASCII碼傳輸,人能直接讀懂
* 引數靈活
* *無連線/無狀態(僅針對HTTP2以前的版本)
## 兩個重要的網站
1.https://www.ietf.org/rfc/
主要儲存RFC標準文件
2.https://zh.wikipedia.org/zh-cn/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE
這個地址是關於HTTP的詳細介紹
## 關於RFC
RFC:Request For Comments(RFC),是一系列以編號排定的檔案。檔案收集了有關網際網路相關資訊,以及UNIX和網際網路社群的軟體檔案。RFC檔案是由Internet Society(ISOC)贊助發行。基本的網際網路通訊協議都有在RFC檔案內詳細說明。RFC檔案還額外加入許多在標準內的論題,例如對於網際網路新開發的協議及發展中所有的記錄。因此幾乎所有的網際網路標準都有收錄在RFC檔案之中。(來自百度百科)
RFC2026將標準定義位4個階段:因特網草案、建議標準、草案標準、因特網標準。更多的過程可以看看這些檔案:
* RFC 2223 "Instructions to RFC Authors"。
* RFC 2026 "The Internet Standards Process -- Revision 3"。
## 瀏覽器輸入某個網站地址並按下回車後發生了什麼
假設我們在瀏覽器鍾輸入www.abc.com,這個網站的IP地址是11.22.33.44,當回車按下後計算機將做如下工作:
1.首先檢查本地的各種快取,比如DNS快取、網站內容快取等,如果有並且規則表明不需在伺服器查詢則直接展示內容出來
2.檢查本地的hosts配置,如果輸入的網站域名在本機有配置則載入本機配置的IP地址,比如我們直接配置了一條hosts如下:
```text
11.22.33.44 www.abc.com
```
那麼計算機將會直接向11.22.33.44這個地址傳送資料,而不會做DNS查詢。
3.如果本機什麼都沒有則進行DNS查詢,DNS和本機的hosts類似,即傳入www.abc.com,然後DNS伺服器返回給機器11.22.33.44,這個DNS伺服器即我們在TCP/IP裡面填寫的伺服器地址,它使用的是UDP傳輸。
4.使用IP建立連線,需要記住的是在網際網路世界裡面只有IP地址才是唯一地址,而網站域名只是一種別名,在連線伺服器的過程中也是使用IP地址進行連線。
5.傳送客戶端請求的資料。
6.接收服務端響應的資料。
當然,實際情形下遠不止以上幾步這麼簡單,以上的每一步也可以拆分位許多小步,甚至形成一篇新的文章,但是基本流程就是這樣。
## 怎麼觀察HTTP協議內容
如上文所說,HTTP協議是基於應用層的協議,那麼計算機網路抓包過後的應用層資料即包含HTTP協議的內容,在windows裡面我們可以採用大名鼎鼎的wireshark進行資料報文的抓取,然後篩選HTTP協議進行觀察,也可以使用smartsniff這樣小而精的軟體專門抓取應用層內容,在Linux裡面直接使用tcpdump進行抓取即可,然後將抓取的結果使用相關的軟體開啟觀察,也可以匯入到wireshark進行觀察。一個實際抓取的較為典型的HTTP內容如下:
``` text
客戶端請求:
POST /devices HTTP/1.1
Host: www.abc.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
a=b&c=d
伺服器響應:
HTTP/1.1 200 OK
Date: Tue, 27 Oct 2020 02:13:39 GMT
Content-Type: application/json
Content-Length: 5
Connection: keep-alive
Server: nginx
Pragma: no-cache
Hello
```
# 協議詳解
## HTTP之URL
HTTP URL格式如下:
```text
http://host[":"port][abs_path]
```
host 表示合法的 Internet 主機域名或者 IP 地址
port 指定一個埠號,為空則使用預設埠 80
abs_path 指定請求資源的 URI
舉幾個例子:
```text
http://www.abc.com
http://www.abc.com:8080
http://www.abc.com/devices
http://www.abc.com:8080/devices/data
http://11.22.33.44/devices/data
http://11.22.33.44:8080/devices/data
```
以上均符合HTTP URL的定義,我們可以簡單地將其理解位我們在瀏覽器裡面輸入的網站域名
## HTTP之請求
### 請求組成部分
http請求由三部分組成,分別是:請求行、訊息報頭、請求正文
### 關於請求行
請求行以一個方法符號開頭,以空格分開,後面跟著請求的URI和協議的版本,即
```text
Method Request-URI HTTP-Version CRLF
```
針對Method有以下定義,並且必須使用以下定義的內容,如果填入其他的資料那麼就不是標準的HTTP協議(雖然一部分伺服器能自動糾錯)
* GET 請求獲取 Request-URI 所標識的資源
* POST 在 Request-URI 所標識的資源後附加新的資料
* HEAD 請求獲取由 Request-URI 所標識的資源的響應訊息報頭
* PUT 請求伺服器儲存一個資源,並用 Request-URI 作為其標識
* DELETE 請求伺服器刪除 Request-URI 所標識的資源
* TRACE 請求伺服器回送收到的請求資訊,主要用於測試或診斷
* CONNECT 保留將來使用
* OPTIONS 請求查詢伺服器的效能,或者查詢與資源相關的選項和需求
常用的Method只有GET以及POST,如果有涉及到協議轉換,比如HTTP1轉換到HTTP2、HTTP轉換到HTTPS或者轉換為websocket,可能回使用OPTIONS方法先詢問。至於其他的方法通常不怎麼用,值得注意的是標準的restful介面業務會在GET和POST基礎上還有PUT和DELETE方法。
針對Request-URI則是我們在瀏覽器輸入的域名和端後後面的內容,比如/devices,如果是根目錄,比如www.abc.com,實際上Request-URI是“/”,即預設都是“/”開始,這樣的目錄結構和Linux的目錄結構類似,而實際上也是來源於它。
HTTP-Version我們常用的是HTTP/1.1,當然,現在也有部分網站使用HTTP/2
第一節的客戶端請求裡面第一行則是請求行的內容,具體如下:
```text
POST /devices HTTP/1.1
```
### 關於訊息報頭
在第一節關於HTTP抓包的請求例項中,除了a=b&c=d這一個內容外其餘的全是訊息報頭,即
```text
Host: www.abc.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
```
這裡面也是HTTP核心東西之一,它以key: value的形式成對出現,除了上述內容外,我們常說的cookie、session等通常情況下也是放在訊息報頭中進行傳輸
我們也常說HTTP Header,直接將訊息報頭理解為HEADER裡面的所有東西也是沒什麼問題的。
### 關於請求正文
上述例子中,“a=b&c=d”即是請求正文,請求正文通常情況下有按照form形式、按照json形式進行傳輸,但是也可以自由發揮填充任意東西,只要服務端能去解析即可。
關於form形式除了最簡單的a=b&c=d外還有mutiform等形式,也是在請求頭中進行定義,然後請求正文使用相應的格式進行資料填充。
### 具體請求例子
具體的例子裡面我們將以最小的報文頭進行展示而展示無關的資訊
* 開啟www.abc.com網站首頁
``` text
GET / HTTP/1.1
Host: www.abc.com
```
* 以GET形式傳入username為haha以及password為hehe到www.abc.com網站的登入介面(假設為/login)
``` text
GET /login?username=haha&password=hehe HTTP/1.1
Host: www.abc.com
```
* 以POST標準FORM形式傳入username為haha以及password為hehe到www.abc.com網站的登入介面(假設為/login)
``` text
POST /login HTTP/1.1
Host: www.abc.com
username=haha&password=hehe
```
* 以POST標準json形式傳入username為haha以及password為hehe到www.abc.com網站的登入介面(假設為/login)
``` text
POST /login HTTP/1.1
Host: www.abc.com
{"username":"haha","password":"hehe"}
```
* 查詢www.abc.com網站的裝置列表,並帶上cookie為123456(假設為/devicelist)
``` text
GET /devicelist HTTP/1.1
Host: www.abc.com
Cookie: 123456
```
* 查詢www.abc.com網站的裝置列表,並帶上cookie為123456,要求服務端保持連線(假設為/devicelist)
``` text
GET /devicelist HTTP/1.1
Host: www.abc.com
Cookie: 123456
Connection: keep-alive
```
# 總結和後續計劃
本文主要講解了HTTP一些基本概念以及請求相關的報文。
接下來第二篇將講解HTTP響應、HTTP2簡介以及當下主流的HTTPS簡單互動過程,最後將模擬請求一次網站並進行抓包