iOS老司機的網路相關Tips

語言: CN / TW / HK

持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第3天,點選檢視活動詳情

1. 前言: 作為一個有自我修養的iOS工程師, 對網路的理解體現在開發中的方方面面

  • 如果你是個科班畢業的iOS開發者, 對計算機網路的基礎認識可能是通過<<計算機網路>>這本教材. image.png
  • 如果你是個其他專業轉向iOS的開發者, 對計算機網路的認識可能來自於這本無數大佬安利的<<圖解HTTP>> image.png
  • 下面就由我們來結合iOS開發日常工作中的方方面, 來一起對iOS中常用的網路相關知識做一個不成體系的梳理, 拋磚引玉, 如在閱讀過程中發現錯誤, 請及時在評論區交流指正:)

2. iOS開發中的網路相關基操Tips

2.1 HTTP的請求方式有哪些?

image.png - GET、POST、PUT、DELETE、HEAD、OPTIONS - 其實我們在開發過程中用的最多的請求方式的是GET和POST, 對其他的⽅式使⽤的很少, 在有些公司採⽤restful⻛格的時候會⽤PUT來做更新, DELETE做刪除.

2.1.1 GET和POST的區別

  • 從用法來說, GET主要是用來獲取資源的, 語義上具有安全性、冪等性、可快取性;
  • 從用法來說, POST主要是用來修改資源的, 語義上具有不安全性、非冪等性、不可快取性;
    • 安全性, 指的是是否能引起server端的變化.
    • 冪等性, 指的是單次請求和多次請求的結果是否一致.
    • 可快取性, 指的是請求是否可以被快取.

2.2 關於HTTP的持久連線的理解

  • 隨著我們要處理的資源越來越多, 如果還是採⽤非持久連線的⽅式就會很浪費資源, 因為會牽扯到⼤量的連線的建⽴和銷燬.
  • 所以為了解決這種問題, 提出了持久連線來改進.
  • 就是在連線建⽴以後, 處理完任務不是⽴即銷燬, ⽽是有⼀個等待時間, 在這段時間範圍內可以對同⼀服務的請求進⾏復⽤, 減少連線的建立和銷燬次數.

2.3 怎樣判斷一個HTTP請求是否已經完成了?

  • 判斷⼀個請求是否完成的⽅式有兩種.
  • 第⼀種: 通過響應報⽂中的content-length欄位來判斷接收的資料是否已經接收完畢了, 如果接收完 畢了就表示本次請求完成了.
  • 第⼆種: 在POST請求中會存在多次響應, 在最後⼀次響應的報⽂中會包含⼀個空的chunck, 我們可以以此來判斷請求是否完成了.

2.4 HTTP連線過程中的三次握手和四次揮手

2.4.1 三次握手

  • 傳送⼀個http請求要先建⽴連線.
  • ⾸先server端要監聽端⼝, 此時server端處於LISTEN狀態.
  • client端傳送⼀個SYN同步包到server端, 並將⾃⼰(client端)的狀態置為SYN_SENT
  • server端收到client的syn, 會回傳⼀個ACK確認資訊, 以及⼀個SYN同步包, 同意建⽴連線, 將server 端狀態置為SYN_RCVD.
  • client端收到服務端的SYN包後, 傳送⼀個ACK給server端. 並將⾃⼰的狀態改為ESTABLISHED.
  • server端接收到ACK資訊後, 會將狀態改為ESTABLISHED.
  • 這樣就完成了三次握⼿, 就可以進⾏資料的傳遞了.

2.4.2 四次揮手

  • 關於斷開連線的四次揮⼿的流程, 主要是因為全雙工通道的機制.
  • client端傳送⼀個FIN訊號給server端, 並進⼊FIN_WAIT_1狀態.
  • server端接收到訊息後會返回⼀個ACK確認, 並進⼊CLOSE_WAIT狀態.
  • client端接收到ACK確認資訊後, 將狀態改為FIN_WAIT_2. 此時已經完成了半關閉狀態.
  • 當server端要傳輸的資料也完成以後, 就會發送⼀個FIN訊號給client端, 並將狀態置為LAST_ACK.
  • client端接收到FIN訊號後會返回⼀個ACK給server端, 並將狀態置為TIME_WAIT.
  • server端在收到ACK確認資訊後, 會進⼊CLOSE狀態.
  • client端會在等待2MSL(報⽂最⼤⽣存時間)的時間後進⼊CLOSE狀態.

2.4.3 為什麼要等待2MSL?

  • 為了保證可靠關閉.
  • 如果server沒有收到最後⼀個ACK, 那麼就會重發FIN.
  • 為了避免端⼝重⽤帶來的資料混淆, 如果client直接進⼊CLOSE狀態, ⼜⽤相同的端⼝建⽴⼀個連線, 上⼀次連線的部分資料在⽹絡中延遲到達server, 資料就有可能發⽣混淆.

2.5 TCP和UDP的區別

  • TCP是傳輸控制協議, 它的特點是: ⾯向連線的、可靠的、⾯向位元組流的, 流量控制、擁塞控制.
  • UDP是⽤戶資料報協議, 它的特點是: ⽆連線、盡最⼤可能交付、⾯向報⽂的, 不保證資料的完整 性.

2.5.1 TCP是怎樣保證傳輸過程的可靠性的?

  • TCP在保證傳輸的可靠性⽅⾯主要有以下機制
  • 校驗和: 傳送⽅在傳送資料之前計算校驗和, 接收⽅收到資料後同樣計算, 如果不⼀致, 那麼傳輸有 誤.
  • 確認應答: TCP進⾏傳輸時資料都進⾏編號, 每次接收⽅返回ACK都有確認序列號.
  • 超時重傳: 如果傳送⽅傳送資料⼀段時間後沒有收到ACK, 那麼就重發資料.
  • 對於超時重傳的情況有兩種
    • ⼀種是客戶端傳送到服務端的資料超時了, 那麼服務端可能會收到兩份資料, 服務端會丟棄重複的資料.
    • 還有⼀種是服務端確認資訊超時了, 那麼客戶端在收到確認資訊的時候什麼都不做.

2.5.2 TCP的流量控制與擁塞控制

image.png - TCP的流量控制是通過滑動窗⼝協議來實現的. TCP協議報⽂頭包含16位的窗⼝⼤⼩, 接收⽅在返回ACK時會把⾃⼰的即時窗⼝填⼊, 傳送⽅就根據報⽂中窗⼝的⼤⼩來控制傳送的速度. - 擁塞控制是為了解決⽹絡中湧⼊⼤量資料包的⼀種機制. - 這⾥主要使⽤慢開始, 擁塞避免和快恢復, 快重傳兩種策略.
- - 慢開始是指剛開始傳送資料的時候, 擁塞窗⼝是1, 以後每次收到ACK後, 將擁塞窗⼝的值按照指數級增⻓, 當增⻓達到了擁塞窗⼝的⻔限值的時候, 就會以線性⽅式增⻓, 來控制傳送資料的速度. - - 當傳送⽹絡擁塞的時候, 就會將擁塞窗⼝值改為1, 重新開始慢開始的流程. 同時將擁塞窗⼝的⻔限值改為擁塞時的⼀半. - - 快恢復快重傳是基於慢開始的, 在發⽣⽹絡擁塞的時候, 是把擁塞窗⼝的⼤⼩調到擁塞值的⼀半, 然後以線性⽅式增⻓.

2.6 DNS域名解析相關

image.png - DNS是做域名解析的, 我們在通過域名訪問伺服器的時候, ⾸先會通過DNS進⾏域名解析, 得到伺服器的IP地址, 然後再進⾏訪問. - 域名解析使⽤的UDP的⽅式進⾏明⽂傳輸的. 採⽤udp是因為它的速度更快. - 但是因為傳輸的明⽂, 所以容易遭到劫持. - 所以在解決DNS劫持的時候主要有兩種⽅式, ⼀種是httpDNS, ⼀種是⻓連線. - - httpDNS是指通過傳送⼀個http請求來解析域名. 因為普通的DNS劫持是基於UDP的, 所以我們通過 httpDNS是採⽤TCP的⽅式, 可以防⽌. - - ⻓連線的⽅式是指我們建⽴⼀個⻓連線伺服器, 讓client與中間伺服器建⽴⻓連線, 並將⻓連線與域名解析伺服器通過內⽹專線的⽅式進⾏連線, 以此來避免DNS的劫持.

2.7 如何保證Cookie的安全

image.png - 對cookie內容進⾏加密處理, 這種⽅式的缺點是不能避免指令碼攻擊. - 在https下傳輸cookie, 這也是我們使⽤最多的⽅式. - 設定cookie為httpOnly來防⽌跨站指令碼攻擊.

2.8 關於HTTPS

  • HTTPS是在HTTP的基礎上增加了安全模組(TLS/SSL).

2.8.1 HTTPS的連線建立流程

image.png 1. ⾸先client端將當前⽀持的TLS版本號, 以及⽀持的加密演算法, 並⽣成⼀個隨機數C⼀起傳送給server端. 2. server端收到訊息後會選擇⼀套加密演算法, 並⽣成⼀個隨機數S, 連同server證書返回給client端 3. client端先校驗server證書, 然後根據預主祕鑰+C+S組裝會話祕鑰. 並通過server證書將預主祕鑰加密傳送給server端. 4. server端⽤私鑰進⾏解碼, 得到預主祕鑰後, 組裝會話祕鑰, 然後加密握⼿訊息.

2.9 ISO模型的七層架構(應表會傳網數物)

  • 七層架構分別是: 應⽤層、表示層、會話層、傳輸層、⽹絡層、資料鏈路層、物理層.
  • 應⽤層: 最⾼層, 直接⾯對⽤戶.
  • 表示層: ⽤來將資料轉換成另外⼀種格式, ⽐如⽂字、影片、圖⽚等.
  • 會話層: 負責建⽴和斷開連線.
  • 傳輸層: TCP、UDP都屬於這⼀層的協議.
  • ⽹絡層: 定義了IP和⼦⽹掩碼, ⽤來確定⽹段, 通過路由器和交換機進⾏傳輸. IP協議就是屬於⽹絡層的協議.
  • 資料鏈路層: 把⽐特流封裝成資料幀的格式.
  • 物理層: 通過⽹線, 光纜等這種物理⽅式將電腦連線起來, 傳遞的是⽐特流.

2.10 什麼是BIO/NIO/AIO?

  • BIO: 同步阻塞IO, 每⼀個客戶端連線, 服務端都會對應⼀個處理執行緒, 對於沒有分配到處理執行緒的連 接就會被阻塞或者拒絕. 相當於⼀個連線⼀個執行緒.

image.png

  • NIO: 同步⾮阻塞IO, 基於Reactor模型, 客戶端和channel進⾏通訊, channel可以進⾏讀寫操作. 通過多路復⽤器seletor來輪詢註冊在其上的channel, ⽽後再進⾏IO操作. 這樣的話, 在進⾏IO操作的時候再⽤⼀個執行緒去處理就好. 也就是⼀個請求⼀個執行緒.

image.png

  • AIO: 非同步⾮阻塞IO, 相⽐NIO更進⼀步, 完全有作業系統來完成請求的處理, 然後通知服務端開啟線 程進⾏處理, 因此是⼀個有效請求⼀個執行緒.

2.11 淺談一下對HTTP的理解

image.png - ⾸先http是超⽂本傳輸協議, 它是基於TCP協議的應⽤層傳輸協議. - 它的特點主要有兩個, ⽆連線和⽆狀態 - - 關於⽆連線是指限制每次連線只處理⼀個請求. 伺服器處理完客戶端的請求, 並收到客戶端的應答後 就斷開連線. 這是早期採⽤的⽅式, 為了追求快, 傳輸的資源少. 但是隨著我們要處理的資源增多, 就提出了持久連線的⽅式, 來複⽤連線, 通過設定⼀個時間, 在這段時間內都可以復⽤此次連線, 只有在超過這個時間後才會斷開連線. - - 關於⽆狀態是指每次請求不會記錄狀態, 為了解決這種⽆狀態的問題, 提出了cookie和session機制. cookie和session都是⽤來記錄⽤戶狀態, 區分⽤戶的. 主要的區別在於cookie是儲存在客戶端, session是儲存在服務端的. session的實現也是基於cookie機制的. - 另外我們在傳送⼀個http請求的時候還主要請求報⽂和響應報⽂. - - 關於請求報⽂主要包含請求⾏, 在請求⾏⾥包含了請求⽅式是GET還是POST, 還有URL, 以及當前協議的版本是http1.0還是1.1. - - 除了請求⾏還有請求的頭部欄位, 這⾥是以key-value的形式存在, 包含多個鍵值對 - - 還有就是實體主體, 在get請求時沒有這⼀塊, 在POST請求時有. - - 關於響應報⽂也包含響應⾏、頭部欄位、以及實體主體. 在響應報⽂的響應⾏中存在著當前的版本、狀態碼、短語, 也就是描述資訊.

2.12 常見的狀態碼

  • 1xx: 目前是協議的中間狀態, 還需要後續請求
    • 100: 請求者應當繼續傳送請求, 服務端返回100表示已收到請求的第一部分, 正在等待剩餘部分.
    • 101: 切換請求協議, 客戶端已要求服務端切換協議, 服務端已確認並準備切換. 如從HTTP切換到WebSocket
  • 2xx: 表示請求成功
    • 200: 請求成功, 有響應體, 伺服器成功返回資料
    • 204: 服務端成功處理了請求, 但沒有返回任何內容(無內容)
    • 205: 服務端成功處理了請求, 但沒有返回任何內容(重置內容)
  • 3xx: 表示重定向狀態, 需要重新請求
    • 301: 永久重定向, 會快取
    • 302: 臨時重定向, 不會快取
    • 304: 協商快取命中
  • 4xx: 表示客戶端請求報文錯誤
    • 400: 請求錯誤, 服務端不理解請求的語法
    • 403: 伺服器禁止訪問, 拒絕請求
    • 404: 資源未找到, 請求的網頁不存在
  • 5xx: 表示服務端錯誤
    • 500: 伺服器端錯誤, 無法完成請求
    • 503: 伺服器繁忙(服務不可用, 由於超載或停機維護, 通常只是暫時狀態)
    • 504: 服務端作為閘道器或代理, 但是沒有及時從上游伺服器收到請求.(閘道器超時)

發文不易, 喜歡點讚的人更有好運氣👍 :), 定期更新+關注不迷路~

ps:歡迎加入筆者18年建立的研究iOS稽核及前沿技術的三千人扣群:662339934,坑位有限,備註“掘金網友”可被群管通過~