在講解 TCP/IP 通訊傳輸流以前,首先複習一下 TCP/IP 的五層協議。編程
應用層:決定向用戶提供應用服務時通訊的活動。TCP/IP 協議族內預存了各種通用的應用服務。好比:FTP、DNS、HTTP 協議。瀏覽器
傳輸層:傳輸層對上層應用層,提供處於網絡鏈接中的兩臺計算機之間的數據傳輸。在傳輸層有兩個性質不一樣的協議,分別是 TCP (Transmission Control Protocol,傳輸控制協議) 和 UDP (User Data Protocol,用戶數據報協議)緩存
網絡層:網絡層用來處理在網絡上流動的數據包。數據包是網絡傳輸的最小數據單位。該層規定了經過怎樣的路徑到達對方計算機,並把數據包傳送給對方。與對方計算機經過多臺計算機或網絡設備進行傳輸時,網絡層所起的做用就是在衆多的選項內選擇一條傳輸路線。bash
數據鏈路層: 在物理層提供比特流服務的基礎上,創建相鄰結點之間的數據鏈路,經過差錯控制提供數據幀 (Frame)在信道上無差錯的傳輸,並進行各電路上的動做系列。數據的單位稱爲幀 (frame)服務器
物理層:物理層創建在物理通訊介質的基礎上,做爲系統和通訊介質的接口,用來實現數據鏈路實體間透明的比特 (bit) 流傳輸。只有該層爲真實物理通訊,其它各層爲虛擬通訊。網絡
TCP/IP 數據傳輸流程併發
客戶端在應用層 (HTTP 協議) 發出一個 HTTP 請求。socket
爲了方便傳輸,在傳輸層 (TCP 協議) 把從應用層處收到的數據 (HTTP 請求報文) 進行分割,並在各個報文上打上標記序號及端口號後轉發給網絡層。tcp
在網絡層 (IP 協議),增長做爲通訊目的地的 MAC 地址後轉發給數據鏈路層。這樣,發送給服務端的請求就準備齊全了。函數
當服務端在鏈路層接收到數據時,按序往上層發送,一直到應用層。當傳輸到應用層時,纔算真正的接收到由客戶端發送過來的請求。
媒體訪問控制地址 (Media Access Control Address),也稱爲局域網地址 (LAN Address),以太網地址 (Ethernet Address) 或物理地址 (Physical Address),它是一個用來確認網上設備位置的地址。ARP (Address Resolution Protocol) 是一種用來解析地址的協議,它能夠根據 IP 地址反查出對應的 MAC 地址。
下圖展現了一臺電腦內網 IP 和 MAC 地址。在終端 (MAC OS 環境) 輸入 ifconfig,找到 en0,即可查找本地以太網的信息。
那麼什麼是 MAC 地址呢?咱們知道 IP 地址是可變的,能夠經過各類方式分配 IP 地址給一個設備,好比 DHCP, PPP,靜態 IP 等。而 MAC 地址通常來說是不會變的,設備在生產時就被「烙」上了 惟一的標識,這個 惟一的標識 就是 MAC 地址。
逼乎上有個頗有趣的例子:你中午在公司點了份外賣,收貨地址必定是寫公司的地址;晚上回到家,再點外賣時就得把地址寫成家 (IP 是動態的)。但不管在哪兒點外賣,訂單上的姓名和手機號必定是你本身的 (MAC 地址)。
中午外賣小哥把午飯送到公司門口,但收外賣的人確定不止你一個 (多臺設備在同一個 broadcast 網絡裏),所以他會經過手機號和姓名來找到你。
用戶數據報協議 (User Datagram Protocol),又稱使用者資料包協議,是一個簡單的面向數據報的傳輸協議。在 TCP/IP 模型中,UDP 爲網絡層以上和應用層如下提供了一個簡單的接口。UDP 只提供數據的 不可靠傳遞,它一旦把應用程序發給網絡層的數據發送出去,就不保留數據備份。UDP 在 IP 數據報的頭部僅僅加入了複用和數據校驗 (字段)。
它的特色以下
UDP 缺少可靠性。UDP 自己不提供確認序號,序列號,超時重傳等機制。UDP 數據報可能在網絡中被複制,被從新排序。即 UDP 不保證數據報會到達其最終目的地,也不保證各個數據報的前後順序,也不保證每一個數據報只到達一次。
UDP 頭部開銷小,它包含如下幾個數據:
兩個十六位的端口號,分別是源端口和目的端口。
整個數據報文的長度。
整個數據報文的校驗和,用於發現頭部信息和數據中的錯誤
複製代碼
UDP 是面向無鏈接的。UDP 客戶端和服務器以前沒必要存在長期的關係。UDP 發送數據報以前也不須要通過握手建立鏈接的過程。
UDP 不只支持單播,還支持多播和廣播。
域名系統 (DNS)
DNS在進行區域傳輸的時候使用TCP協議,其它時候則使用UDP協議;
複製代碼
簡單網絡管理協議 (SNMP)
動態主機配置協議 (DHCP)
路由信息協議 (RIP)
TCP (Transmission Control Protocol, 傳輸控制協議) 是一種面向鏈接的、可靠的、基於字節流服務的傳輸層通訊協議,由 IETF 的 RFC 793 定義。其中字節流服務 (Byte Stream Service) 是指爲了方便傳輸,將大塊數據分割成以報文段 (segment) 爲單位的數據包進行管理。
TCP 提供一種面向鏈接的、可靠的字節流服務
在一個 TCP 鏈接中,僅有兩方進行彼此通訊。廣播和多播不能用於 TCP
TCP 使用校驗和,確認和重傳機制來保證可靠傳輸
TCP 給數據分節進行排序,並使用累積確認保證數據的順序不變和非重複
TCP 使用滑動窗口機制來實現流量控制,經過動態改變窗口的大小進行擁塞控制
TCP 報文
端口號:包括源端口號和目的端口號,用來標識同一臺計算機的不一樣的應用進程。TCP 報頭中的源端口號和目的端口號同 IP 數據報中的源 IP 與目的 IP 惟一肯定一條 TCP 鏈接。源端口號:源端口和 IP 地址的做用是標識報文的返回地址。
目的端口號:目的端口指明接收方計算機上的應用程序接口。
序號:它是當前報文段發送的數據組的第一個字節的序號。在 TCP 傳送的流中,每個字節一個序號。好比一個報文段的序號爲 300,此報文段的數據部分共有 100 字節,則下一個報文段的序號爲 400。序號 確保了 TCP 傳輸的有序性。
**確認號:**即 ACK(acknowledgement),指明下一個期待收到的字節序號,代表該序號以前的全部數據已經正確無誤的收到。確認號只有當 ACK 標誌爲 1 時纔有效。好比創建鏈接時,SYN 報文的 ACK 標誌位爲 0。
首部長度:因爲首部可能含有可選項內容,所以 TCP 報頭的長度是不肯定的,報頭不包含任何任選字段則長度爲 20 字節,4 位首部長度字段所能表示的最大值爲 1111,轉化爲 10 進製爲 15,15*32/8 = 60,故報頭最大長度爲 60 字節。首部長度也叫數據偏移,是由於首部長度實際上指示了數據區在報文段中的起始偏移值。
保留:爲未來定義新的用途保留,如今通常置 0。
窗口:滑動窗口大小,用來告知發送端接受端的緩存大小,以此控制發送端發送數據的速率,從而達到流量控制。窗口大小是一個 16bit 字段,所以窗口大小最大爲 65535。
校驗和:奇偶校驗,此校驗和是對整個的 TCP 報文段,包括 TCP 頭部和 TCP 數據,以 16 位字進行計算所得。由發送端計算和存儲,並由接收端進行驗證。
緊急指針:只有當 URG 標誌置 1 時緊急指針纔有效。緊急指針是一個正的偏移量,和順序號字段中的值相加表示緊急數據最後一個字節的序號。 TCP 的緊急方式是發送端向另外一端發送緊急數據的一種方式。
選項和填充:最多見的可選字段是最長報文大小,又稱爲 MSS (Maximum Segment Size),每一個鏈接方一般都在通訊的第一個報文段 (爲創建鏈接而設置 SYN 標誌爲 1 的那個段)中指明這個選項,它表示本端所能接受的最大報文段的長度。選項長度不必定是 32 位的整數倍,因此要加填充位,即在這個字段中加入額外的零,以保證 TCP 頭是 32 的整數倍。
數據部分:TCP 報文段中的數據部分是可選的。在一個鏈接創建和一個鏈接終止時,雙方交換的報文段僅有 TCP 首部。若是一方沒有數據要發送,也使用沒有任何數據的首部來確認收到的數據。在處理超時的許多狀況中,也會發送不帶任何數據的報文段。
上面寫了那麼可能是不是不太好記,其實不用全都記住,記住個大概流程
複製代碼
所謂三次握手 (three-way handshaking) 是指創建一個 TCP 鏈接時,須要客戶端和服務端共發送三個包。它的目的是鏈接服務器指定端口,創建 TCP 鏈接,並同步雙方的 序列號 和 確認號,交換 TCP 窗口大小信息。在 socket 編程中,當客戶端執行 connect() 函數時,將觸發三次握手。
SYN:同步序列編號(Synchronize Sequence Numbers)。是TCP/IP創建鏈接時使用的握手信號。在客戶機和服務器之間創建正常的TCP網絡鏈接時,客戶機首先發出一個SYN消息,服務器使用SYN+ACK應答表示接收到了這個消息,最後客戶機再以ACK消息響應。這樣在客戶機和服務器之間才能創建起可靠的TCP鏈接,數據才能夠在客戶機和服務器之間傳遞。
seq:序列號,什麼意思呢?當發送一個數據時,數據是被拆成多個數據包來發送,序列號就是對每一個數據包進行編號,這樣接受方纔能對數據包進行再次拼接。
ack:這個表明下一個數據包的編號,這也就是爲何第二請求時,ack是seq+1,
第一次握手
客戶端首先發送一個 SYN 爲 1 的包給服務端,指明客戶端要鏈接服務端的哪一個接口以及初始序號 x。發送完畢後,客戶端進入 SYN_SEND 狀態。
第二次握手
服務端收到後,回傳一個帶有 SYN/ACK 的確認包以示應答。即 SYN=1,ACK=1。服務端選擇本身的 ISN 序列號,放到 seq 中,同時將確認序號 ack 設置爲客戶端的 ISN+1,即 x+1。發送完畢後,服務端進入 SYN_RCVD (同步收到) 狀態。
第三次握手
客戶端收到確認後,再次發送一個帶 ACK 標誌的數據包。即 ACK=1,ack=y+1,並將本身的序列號 seq=x+1。發送完畢後,客戶端和服務器雙雙進入 ESTABLISHED 狀態。至此,三次握手結束。
爲何是三次握手,兩次不行嗎?
爲了實現可靠數據傳輸,TCP 協議的通訊雙方,都必須維護一個序列號,以標識發送出去的數據包中,哪些是已經被對方收到的。三次握手的過程便是通訊雙方相互告知序列號起始值,並確認對方已經收到了序列號起始值的必經步驟
若是隻是兩次握手,至多隻有鏈接發起方的起始序列號能被確認,另外一方選擇的序列號則得不到確認。
若是已經創建了鏈接,可是客戶端忽然出現故障了怎麼辦?
TCP 還設有一個保活計時器 (keep-alive),若是客戶端出現故障,服務器不能一直等下去,白白浪費資源。服務器每收到一次客戶端的請求後都會從新復位這個計時器,時間一般是設置爲 2 小時,若兩小時尚未收到客戶端的任何數據,服務器就會發送一個探測報文段,之後每隔 75 秒發送一次。若一連發送 10 個探測報文仍然沒反應,服務器就認爲客戶端出了故障,接着就關閉鏈接。
TCP 關閉鏈接 (四次揮手)
第一次揮手
客戶端調用 close() 函數,併發送一個 FIN (finish) 標誌爲 1 的數據包給服務端,來表示本方的數據已經所有發送完畢,此時客戶端進入 FIN_WAIT_1 狀態。TCP 規定,FIN 報文段即便不攜帶數據,也要消耗一個序號。
第二次揮手
服務端收到客戶端的釋放報文後,發出確認報文,其中 ACK=1, ack=u+1,而且帶上本身的序列號 seq=v。代表本身接受到了客戶端關閉鏈接的請求,但還沒準備好關閉鏈接 (半關閉狀態),也就是說客戶端已經沒有數據要發送了,但服務端仍有可能會發送數據。發送完畢後,服務端進入 CLOSE_WAIT 狀態。
當客戶端收到該報文後,客戶端就進入 FIN-WAIT-2 狀態,等待服務器發送鏈接釋放報文。
第三次揮手
服務器端準備好關閉鏈接時,會向客戶端發送一個鏈接釋放報文,其中 FIN=1,ack=u+1。因爲在半關閉狀態,服務器極可能又發送了一些數據,假定此時的序列號爲 seq=w。發送完畢後,服務端便進入 LAST-ACK(最後確認) 狀態。
第四次揮手
客戶端收到服務器的鏈接釋放報文後,須要發送一個確認包,其中 ACK=1,ack=w+1,而本身的序列號是 seq=u+1,並進入了 TIME-WAIT (時間等待)狀態,等待過程可能出現的要求重傳的 ACK 包。
此時 TCP 鏈接尚未釋放,必須通過 2 * MSL (Maximum Segment Lifetime, 最長報文段壽命) 時間後,當客戶端撤銷相應的 TCB 後,纔會進入 CLOSED 狀態。
而服務器只要收到了客戶端發出的確認,當即進入 CLOSED 狀態。一樣,撤銷 TCB 後,就結束了此次的 TCP 鏈接。所以,服務器結束 TCP 鏈接的時間要比客戶端早一些。
請求報文和 DNS 服務器返回的應答報文都是統一的格式:
會話標識 (2 字節):它是 DNS 報文的 ID 標識,對於請求報文和其對應的應答報文,這個字段是相同的,經過它能夠區分 DNS 應答報文是哪一個請求的響應。
標誌 (2 字節):它有 8 個部分,以下圖所示:
Questions 查詢字段
QNAME 無符號 8bit 爲單位長度不限表示查詢名。
QTYPE 無符號 16bit 整數表示查詢的協議類型。
QCLASS 無符號 16bit 整數表示查詢的類。
Answer/Authority/Additional
三者的格式相同,以下所示:
折騰過搭建網站的小夥伴們必定對 DNS 解析記錄不會陌生,下面經過表格複習一下。
系統會檢查瀏覽器緩存中有沒有這個域名對應的解析過的 IP 地址,若是緩存中有,這個解析過程就將結束。瀏覽器緩存是受這個域名的失效時間和緩存的空間大小控制的。
若是用戶的瀏覽器緩存中沒有,瀏覽器會查找操做系統緩存中即爲本地的 Host 文件。
路由器也可能會有緩存。
若是前幾步都沒有找到,就會到 LDNS (Local DNS) 中查找,LDNS 是你的 ISP 分配給你的 DNS (通常爲兩個),大部分狀況下域名都會在這裏獲得解析。下圖是 cloudflare 提供給個人兩個 DNS。