自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試反客為主 TCP

網(wǎng)絡(luò) 通信技術(shù)
承接上文 HTTP,數(shù)據(jù)經(jīng)過應(yīng)用層就到傳輸層,但數(shù)據(jù)到傳輸層之前需要先獲得服務(wù)端的 IP 地址,這就涉及到 DNS 域名解析。

[[381851]]

本文轉(zhuǎn)載自微信公眾號(hào)「sowhat1412」,作者SoWhat1412。轉(zhuǎn)載本文請(qǐng)聯(lián)系sowhat1412公眾號(hào)。

3 傳輸層 TCP/UDP

承接上文 HTTP,數(shù)據(jù)經(jīng)過應(yīng)用層就到傳輸層,但數(shù)據(jù)到傳輸層之前需要先獲得服務(wù)端的 IP 地址,這就涉及到 DNS 域名解析。

3.1 DNS

3.1.1 DNS 講解

主機(jī)的真正地址是 IP ,問題是 IP 地址不方便人們記憶,就像你拿手機(jī)給張三打電話,難道你能瞬間說出張三電話號(hào)碼么,手機(jī)里做一個(gè)名字跟電話的映射即可,想通話時(shí)直接從通訊錄找到張三就可以找到對(duì)應(yīng)的手機(jī)號(hào),在網(wǎng)絡(luò)請(qǐng)求時(shí)候也是需要映射的,而域名服務(wù)器 Domain Name System 就是干這個(gè)事的,深入講 DNS 前先了解下域名。

我們?cè)跒g覽器地址欄中輸入的每一個(gè)地址都是一個(gè)域名,比如 www.baidu.com。域名是由.和不同級(jí)別域的域名組成。通常我們?cè)跁鴮憰r(shí)會(huì)省略根域名,即域名結(jié)尾的.,如www.baidu.com.。由于域名是老外發(fā)明的所以從左到右范圍逐步變大且以.分割。

DNS分層

 

由上到下域名之間相互包含跟嵌套,根域名服務(wù)器是關(guān)鍵,必須是眾所周知的,找到了它,下面的各級(jí)域名服務(wù)器才能找到,否則域名解析就無從談起了。我們看下請(qǐng)求 www.baidu.com 的 DNS 解析流程:

  1. 首先訪問根域名服務(wù)器,根域名是不做域名解析,只是給你指路用的,現(xiàn)在你獲取 com 頂級(jí)域名服務(wù)器的地址。
  2. 請(qǐng)求 com 頂級(jí)域名服務(wù)器,返回 baidu.com 域名服務(wù)器的地址。
  3. 然后請(qǐng)求 baidu.com 域名服務(wù)器,返回 www.baidu.com 的地址。

這樣進(jìn)行 DNS 的流程是OK的,但問題是全球數(shù)十億的PC電腦,如果每個(gè)電腦請(qǐng)求上網(wǎng)都按照上面流程走一波,那上面的 DNS 核心解析系統(tǒng)瞬間爆炸!解決辦法就是用緩存,很多大公司跟運(yùn)營(yíng)商都會(huì)搭建自己的 DNS 服務(wù)器來代替用戶請(qǐng)求核心 DNS 系統(tǒng),如果查到的話可以緩存查詢記錄,再次收到請(qǐng)求的號(hào)如果有緩存結(jié)果或者緩存未過期,則直接返回原來的緩存結(jié)果,知名的 Google 8.8.8.8 DNS 解析服務(wù)器,就是 Google 自建的非權(quán)威域名服務(wù)器 。除了非權(quán)威域名服務(wù)器,我們經(jīng)常看到的有瀏覽器緩存,操作系統(tǒng)緩存,比如 /etc/hosts文件等。

3.1.2 DNS 樣例

DNS域名解析

 

  1. 用戶輸入網(wǎng)址先看下瀏覽器的DNS緩存是否過期,沒過期直接拿來用。過期了看看本地操作系統(tǒng)緩存 /etc/hosts 文件等。
  2. 請(qǐng)求本地配置的 非權(quán)威域名服務(wù)器 DNS resolver。
  3. DNS resolver 將網(wǎng)址轉(zhuǎn)發(fā)到根域名請(qǐng)求,返回 com 域名地址。
  4. DNS resolver 將網(wǎng)址轉(zhuǎn)發(fā)到 com 域名的服務(wù)器請(qǐng)求,返回跟 baidu.com 相關(guān)的 權(quán)威DNS解析器。
  5. DNS resolver 將網(wǎng)址轉(zhuǎn)發(fā)權(quán)威 DNS 解析器繼續(xù)請(qǐng)求,然后返回真正的目標(biāo)域名IP。
  6. DNS resolver 最終將目標(biāo) IP 返回給用戶繼續(xù)接下來的訪問請(qǐng)求。

3.2 TCP

3.2.1 TCP 頭部講解

TCP 是一個(gè)是面向連接的、可靠的、基于字節(jié)流的、工作在傳輸層的數(shù)據(jù)傳輸服務(wù)。用 TCP 傳輸數(shù)據(jù)能確保接收端接收的網(wǎng)絡(luò)包是無損壞、無間隔、非冗余、有序。這里需注意 TCP 是一對(duì)一連接的。

TCP頭部 + HTTP

 

  1. 發(fā)送端口:是一個(gè)大于 1023 的 16 位數(shù)字,由基于TCP應(yīng)用程序的用戶進(jìn)程隨機(jī)選擇。
  2. 目的端口:指明接收者所用的端口號(hào),一般由應(yīng)用程序來指定。
  3. 序列號(hào):建立連接時(shí)客戶端生成隨機(jī)數(shù)作為初始值,通過 SYN 包傳給接收端主機(jī),每發(fā)送一次數(shù)據(jù),就累加一次。序列號(hào)達(dá)到最大值會(huì)出現(xiàn)序列號(hào)回繞,再次從0 開始。核心作用就是 接收方去重?cái)?shù)據(jù) + 按序接收。
  4. 確認(rèn)號(hào):用來解決不丟包的問題,指定下一次希望收到的數(shù)據(jù)的序列號(hào),發(fā)送端收到這個(gè)確認(rèn)應(yīng)答以后可以認(rèn)為在這個(gè)序號(hào)以前的數(shù)據(jù)都已經(jīng)被正常接收。
  5. 數(shù)據(jù)偏移:表示 TCP 報(bào)文段的首部長(zhǎng)度,4 位二進(jìn)制最大表示15,由于TCP首部包含個(gè)可變長(zhǎng)度選項(xiàng),需要指定這個(gè) TCP 報(bào)文段到底有多長(zhǎng)。它指出 TCP 報(bào)文段的數(shù)據(jù)起始處距離 TCP 報(bào)文段的起始處有多遠(yuǎn)。該字段的單位是4字節(jié),所以TCP首部最大15*4 = 60字節(jié)。
  6. 保留:保留6位,未使用,應(yīng)置零。

下面的7~12是控制位,用來表示說明報(bào)文段的性質(zhì)

7.URG:表示本報(bào)文段中發(fā)送的數(shù)據(jù)是否包含緊急數(shù)據(jù)。只有當(dāng) URG=1 時(shí)后面的緊急指針字段urgent pointer才有效。

8.ACK:表示是否前面確認(rèn)號(hào)字段是否有效。只有當(dāng) ACK=1 時(shí),前面的確認(rèn)號(hào)字段才有效。TCP 規(guī)定連接建立后 ACK=1,帶 ACK 標(biāo)志的TCP報(bào)文段稱為確認(rèn)報(bào)文段。

9.PSH:提示接收端需立即從 TCP 接收緩沖區(qū)中讀走數(shù)據(jù),為接收后續(xù)數(shù)據(jù)騰出空間。為1表示對(duì)方應(yīng)當(dāng)立即把數(shù)據(jù)提交給上層應(yīng)用,如果應(yīng)用程序不將接收到的數(shù)據(jù)讀走,就會(huì)一直停留在 TCP 接收緩沖區(qū)中。

10.RST:收到一個(gè) RST=1 的報(bào)文說明與主機(jī)的連接出現(xiàn)了嚴(yán)重錯(cuò)誤,必須釋放連接,然后再重新建立連接。或者說明上次發(fā)送給主機(jī)的數(shù)據(jù)有問題,主機(jī)拒絕響應(yīng),帶 RST 標(biāo)志的 TCP 報(bào)文段稱為復(fù)位報(bào)文段。

11.SYN:建立連接時(shí)用來同步序號(hào)。SYN=1 說明這是一個(gè)請(qǐng)求建立連接或同意建立連接的報(bào)文。只有在前兩次握手中 SYN 才置為1,帶 SYN 標(biāo)志的 TCP 報(bào)文段稱為同步報(bào)文段。

  • 當(dāng) SYN=1 且 ACK=0 時(shí)表示這是一個(gè)請(qǐng)求建立連接的報(bào)文段。
  • 當(dāng) SYN=1 且 ACK=1 時(shí)表示對(duì)方同意建立連接。

12FIN:通知對(duì)方本端要關(guān)閉連接了,標(biāo)記數(shù)據(jù)是否發(fā)送完畢。如果 FIN=1 告訴對(duì)方釋放連接,帶FIN標(biāo)志的TCP報(bào)文段稱為結(jié)束報(bào)文段。

13.窗口大?。罕硎粳F(xiàn)在允許對(duì)方發(fā)送的數(shù)據(jù)量,告訴對(duì)方從本報(bào)文段的確認(rèn)號(hào)開始允許對(duì)方發(fā)送的數(shù)據(jù)量,達(dá)到此值,需要ACK確認(rèn)后才能再繼續(xù)傳送后面數(shù)據(jù)。

14.校驗(yàn)和:提供額外的可靠性。

15.緊急指針:標(biāo)記緊急數(shù)據(jù)在數(shù)據(jù)字段中的位。

16.選項(xiàng)部分:選項(xiàng)部分的最大長(zhǎng)度可根據(jù)TCP首部長(zhǎng)度進(jìn)行推算。TCP首部長(zhǎng)度用4位表示,選項(xiàng)部分最長(zhǎng)為:(2^4-1)*4-20=40 字節(jié)。

TCP 只規(guī)定了一種選項(xiàng),即TCP報(bào)文段最大長(zhǎng)度 MSS,通常是1460字節(jié),整個(gè)TCP報(bào)文段的長(zhǎng)度 = 數(shù)據(jù)字段的長(zhǎng)度 + TCP 首部的長(zhǎng)度 。

17.填充:這里需注意,為了網(wǎng)絡(luò)設(shè)備硬件設(shè)計(jì)和處理方便, 數(shù)據(jù)傳輸過程中首部長(zhǎng)度必須是 4 字節(jié)的整數(shù)倍。

3.2.2 TCP 三次握手

TCP三次握手

 

  1. 一開始客戶端跟服務(wù)器都處于 closed 狀態(tài),然后服務(wù)端主動(dòng)監(jiān)聽某個(gè)客戶端端口,此時(shí)服務(wù)端處于listen 狀態(tài)。
  2. 客戶端隨機(jī)初始化序列號(hào) seq = client_isn,同時(shí)將 SYN = 1 表示這是SYN 報(bào)文,接著把該 SYN 報(bào)文發(fā)給服務(wù)器,注意此時(shí)報(bào)文不包含引用層數(shù)據(jù),客戶端處于 syn-sent狀態(tài)。
  3. 服務(wù)端收到客戶端的 SYN報(bào)文后也隨機(jī)初始化個(gè)序號(hào) seq = server_isn,并且將確認(rèn)序號(hào) ack = client_isn + 1,接著把 SYN = 1跟 ACK = 1,然后該報(bào)文發(fā)送給客戶端,服務(wù)器處于 syn-rcvd狀態(tài)。
  4. 客戶端收到服務(wù)器的報(bào)文后,將 ACK = 1,確認(rèn)應(yīng)答號(hào) ack = server_isn + 1,然后把報(bào)文發(fā)送給服務(wù)器,本次報(bào)文可發(fā)送數(shù)據(jù),同時(shí)客戶端處于established 狀態(tài)。
  5. 服務(wù)器收到客戶端的應(yīng)答報(bào)文后,也進(jìn)入 established 狀態(tài)。
  6. 客戶端和服務(wù)端建立好了連接,可以相互發(fā)送數(shù)據(jù)。

這里你可能發(fā)現(xiàn)了客戶端跟服務(wù)器的初始化序列號(hào)是各自隨機(jī)的,原因是網(wǎng)絡(luò)中的報(bào)文會(huì)重發(fā)、會(huì)延遲、也有可能丟失,為避免相互影響干脆各用各的為好。同時(shí)通過流程發(fā)現(xiàn)前兩次握手是不帶數(shù)據(jù)的,第三次可攜帶數(shù)據(jù)。

3.2.3 TCP 數(shù)據(jù)傳輸大致流程

前面在HTTP時(shí)候就說過了,數(shù)據(jù)到TCP層跟IP層都會(huì)拆分發(fā)送,有人可能會(huì)問:既然IP會(huì)分幀,那為什么TCP層還分層呢?原因是如果TCP不分層,只用IP層分幀數(shù)據(jù)發(fā)送,如果有一幀出現(xiàn)丟失則會(huì)導(dǎo)致整個(gè)IP報(bào)文分幀全部重傳。本質(zhì)在于IP層沒有重傳機(jī)制而TCP層可以實(shí)現(xiàn)數(shù)據(jù)的超時(shí)重傳、丟失重傳。

信息傳輸大致流程

 

3.2.4 TCP 狀態(tài)查詢

服務(wù)器一般用 netstat 查看 tcp,udp 的端口和進(jìn)程等相關(guān)情況。netstat -tunlp | grep 端口號(hào)

  1. -t (tcp) 僅顯示tcp相關(guān)選項(xiàng) 
  2. -u (udp) 僅顯示udp相關(guān)選項(xiàng) 
  3. -n 拒絕顯示別名,能顯示數(shù)字的全部轉(zhuǎn)化為數(shù)字 
  4. -l 僅列出在Listen(監(jiān)聽)的服務(wù)狀態(tài) 
  5. -p 顯示建立相關(guān)鏈接的程序名 

netstat樣例

 

3.2.5 TCP 為啥三次握手

TCP是不區(qū)分客戶端和服務(wù)端,連接的建立是雙向的過程。所以客戶端要給服務(wù)器通訊的話兩次握手是必須的。

  1. 第一次握手客戶端發(fā)個(gè)連接請(qǐng)求給服務(wù)端,服務(wù)端收到后知道自己可以跟客戶端連接了,
  2. 但是此時(shí)客戶端不知道啊,所以必須的執(zhí)行第二次握手,反饋下信息給客戶端。
  3. 第一次握手請(qǐng)求連接如果因?yàn)榫W(wǎng)絡(luò)導(dǎo)致延遲,直到連接釋放后信息才到達(dá)服務(wù)端,那此時(shí)服務(wù)端也會(huì)給客戶端進(jìn)行第二次握手回復(fù),關(guān)鍵是客戶端已經(jīng)不要這個(gè)連接了,此時(shí)服務(wù)端會(huì)一直在等待接收客戶端信息,造成資源浪費(fèi)。
  4. 如果用了三次握手則客戶端會(huì)發(fā)送 RST 報(bào)文告知服務(wù)端請(qǐng)終止本次舊連接。

如果還不太理解,我們用個(gè)生活常識(shí)說明下。晚上你在小區(qū)里散步,不遠(yuǎn)處看見一位漂亮妹子迎面而來,因?yàn)槁窡粲悬c(diǎn)暗不能100%確認(rèn),所以要通過招手的方式來確定對(duì)方是否認(rèn)識(shí)自己。

1. 你首先向妹子 招手 syn。

2. 妹子看到你向自己招手后,向你點(diǎn)頭 微笑 ack。

3. 她也需要確認(rèn)一下你有沒有可能你是在看別人呢,妹子也向你 招手 syn。

4. 你看到妹子 微笑ack 后確認(rèn)了妹子成功辨認(rèn)出了自己,進(jìn)入 established 狀態(tài)。

5. 妹子給你 招手 syn 了,你也 微笑 ack 回復(fù),妹子收到后也進(jìn)入 established 狀態(tài)。

因?yàn)槊米舆B續(xù)進(jìn)行了兩個(gè)動(dòng)作,先是點(diǎn)頭微笑,然后再次招手,所以可以將這兩個(gè)動(dòng)作合成一個(gè)動(dòng)作,招手的同時(shí)點(diǎn)頭和微笑。于是這四個(gè)動(dòng)作就簡(jiǎn)化成了三個(gè)動(dòng)作。

你與妹子的相識(shí)

 

3.2.6 TCP 三次握手的意義

1.避免歷史連接

客戶端建立連接時(shí)發(fā)送多次 SYN 報(bào)文,由于網(wǎng)絡(luò)擁堵可能舊的 SYN 報(bào)文比新的 SYN 報(bào)文先到服務(wù)器,服務(wù)器不管新舊,收到就回復(fù) SYN + ACK 給客戶端,三次握手情況下客戶端可以根據(jù)序列號(hào)或超時(shí)時(shí)間判斷回復(fù)的連接是否是歷史連接,如果是歷史連接直接發(fā)送 RST 報(bào)文給服務(wù)端來終止連接。

2.同步雙方初始序列號(hào)

TCP 協(xié)議的通信雙方都在維護(hù)各自的序列號(hào),且必須要讓對(duì)方知道。只有通過三次握手才可以實(shí)現(xiàn)。

3.避免服務(wù)端資源浪費(fèi)

二次握手情況下,如果客戶端的 SYN 阻塞導(dǎo)致重復(fù)發(fā)送多次 SYN 報(bào)文,那么服務(wù)器在收到請(qǐng)求后就會(huì)建立多個(gè)冗余的無效鏈接,造成不必要的資源浪費(fèi)。而三次握手發(fā)現(xiàn)無效鏈接可在第三次給服務(wù)器端發(fā)送終止指令。

3.2.7 TCP 連接中客戶端忽然掛掉咋辦?

TCP還設(shè)有一個(gè)?;钣?jì)時(shí)器,服務(wù)器每收到一次客戶端的請(qǐng)求后都會(huì)重新復(fù)位這個(gè)計(jì)時(shí)器,時(shí)間通常是設(shè)置為2小時(shí),若兩小時(shí)還沒有收到客戶端的任何數(shù)據(jù),服務(wù)器就會(huì)發(fā)送一個(gè)探測(cè)報(bào)文段,以后每隔75秒發(fā)送一次。若一連發(fā)送10個(gè)探測(cè)報(bào)文仍然沒反應(yīng),服務(wù)器就認(rèn)為客戶端出了故障,接著就關(guān)閉連接。

3.2.8 TCP 如何避免 SYN 攻擊

TCP 連接時(shí)會(huì)經(jīng)過三次握手,在第一次握手后,服務(wù)端收到 SYN 報(bào)文 就會(huì)發(fā)出 ACK + SYN 報(bào)文 同時(shí)進(jìn)入 SYN_RCVD 狀態(tài),如果有黑客偽造 n 個(gè)不同 IP 發(fā)出請(qǐng)求,會(huì)導(dǎo)致服務(wù)器的 SYN_RCVD 隊(duì)列 爆滿,最終無法對(duì)外提供服務(wù)。

解決方法:

  1. 設(shè)置 SYN_RCVD 最大值:服務(wù)端超過處理能力時(shí),直接將新的 SYN 請(qǐng)求 RST 丟棄。
  2. 可縮短 SYN Timeout 時(shí)間:通過縮短從接收到 SYN 報(bào)文到確定這個(gè)報(bào)文無效并丟棄該連接的時(shí)間,可以降低服務(wù)器負(fù)荷。
  3. 設(shè)置SYN Cookie:給每個(gè)請(qǐng)求連接的 IP 地址分配一個(gè) Cookie,如果短時(shí)間內(nèi)收到同一個(gè) IP 的重復(fù) SYN 報(bào)文,則以后從這個(gè) IP 地址來的包會(huì)被丟棄。

3.2.9 TCP 四次揮手

客戶端跟服務(wù)端都可以發(fā)出端口請(qǐng)求,TCP 斷開連接是通過四次揮手方式。

TCP四次揮手

 

  1. 客戶端停止發(fā)送數(shù)據(jù)并且發(fā)出釋放連接的報(bào)文,報(bào)文中FIN = 1,F(xiàn)IN報(bào)文段即使不攜帶數(shù)據(jù),也要消耗一個(gè)序號(hào),此時(shí)序列號(hào)seq = u ,u = 前面已經(jīng)傳輸過來數(shù)據(jù)最后一個(gè)字節(jié)序號(hào)加1,客戶端進(jìn)入FIN-WAIT-1狀態(tài)。
  2. 服務(wù)器收到連接釋放報(bào)文,發(fā)出確認(rèn)報(bào)文,ACK=1,應(yīng)答確認(rèn)好 ack=u+1,并且?guī)献约旱男蛄刑?hào)seq=v,此時(shí)服務(wù)端就進(jìn)入了CLOSE-WAIT 狀態(tài)。TCP 服務(wù)器通知高層的應(yīng)用進(jìn)程進(jìn)入半閉狀態(tài),即客戶端已經(jīng)沒有數(shù)據(jù)要發(fā)送了,但是服務(wù)器若發(fā)送數(shù)據(jù),客戶端依然要接受。這個(gè)狀態(tài)還要持續(xù)一段時(shí)間,也就是整個(gè) CLOSE-WAIT狀態(tài)持續(xù)的時(shí)間。
  3. 客戶端收到服務(wù)器的確認(rèn)請(qǐng)求后,此時(shí)客戶端就進(jìn)入FIN-WAIT-2 狀態(tài),等待服務(wù)器發(fā)送連接釋放報(bào)文,在這之前還需要接受服務(wù)器發(fā)送的最后的數(shù)據(jù)。
  4. 服務(wù)器將最后的數(shù)據(jù)發(fā)送完畢后,就向客戶端發(fā)送連接釋放報(bào)文,F(xiàn)IN=1,ack=u+1,由于在半關(guān)閉狀態(tài),服務(wù)器很可能又發(fā)送了一些數(shù)據(jù),假定此時(shí)的序列號(hào)為 seq=w,此時(shí)服務(wù)器就進(jìn)入了LAST-ACK 狀態(tài),等待客戶端的確認(rèn)。
  5. 客戶端收到服務(wù)器的連接釋放報(bào)文后必須發(fā)出確認(rèn),ACK=1,ack=w+1,seq=u+1,此時(shí)客戶端就進(jìn)入了TIME-WAIT狀態(tài)。注意此時(shí) TCP 連接還沒有釋放,必須經(jīng)過最長(zhǎng)報(bào)文段壽命 2MSL 的時(shí)間后,當(dāng)客戶端撤銷相應(yīng)的 TCB 后,才進(jìn)入 CLOSED 狀態(tài)。
  6. 服務(wù)器只要收到了客戶端發(fā)出的確認(rèn),立即進(jìn)入 CLOSED 狀態(tài)。同樣撤銷 TCB后,就結(jié)束了這次的 TCP 連接,可以看到服務(wù)器結(jié)束TCP連接的時(shí)間要比客戶端早一些。

我們還以你跟妹子碰面交流為例,你倆彼此確認(rèn)后交流幾分鐘后,你打算結(jié)束這個(gè)談話,畢竟交流太久沒老婆發(fā)現(xiàn)就涼了。

你跟妹子揮手離別

 

3.2.10 TCP 為什么四次揮手

其實(shí)分析下整個(gè)關(guān)閉的流程就知道為什么必須是四次揮手而不是三次揮手了。

  1. 關(guān)閉連接時(shí),客戶端向服務(wù)端發(fā)送 FIN 時(shí),僅僅表示客戶端不再發(fā)送數(shù)據(jù)出去了但是還是能接收數(shù)據(jù)。
  2. 服務(wù)器收到客戶端的 FIN 報(bào)文時(shí),先回一個(gè) ACK應(yīng)答報(bào)文,意思是不再接受數(shù)據(jù)了,但服務(wù)端可能還有數(shù)據(jù)需往外發(fā)送,等服務(wù)端不再發(fā)送數(shù)據(jù)時(shí)才發(fā)送 FIN 報(bào)文給客戶端來表示同意現(xiàn)在關(guān)閉連接。這里注意服務(wù)端的 ACK 跟 FIN 是分開發(fā)的。
  3. 客戶端收到服務(wù)端的 ACK 后,再給服務(wù)端發(fā)送 ACK,最終客戶端跟服務(wù)器都進(jìn)入close 狀態(tài)。

3.2.11 TCP 揮手為什么需要 TIME_WAIT 狀態(tài)

MSL 定義:

Maximum Segment Lifetime 報(bào)文最大生存時(shí)間,意思是網(wǎng)絡(luò)傳輸?shù)膱?bào)文在網(wǎng)絡(luò)上存在的最長(zhǎng)時(shí)間,超過這個(gè)時(shí)間報(bào)文將被丟棄。而數(shù)據(jù)之所以可以被拋棄是因?yàn)門CP層的下面的IP層有個(gè)TTL來記錄報(bào)文傳輸過程中經(jīng)過的最大路由次數(shù)。

TIME_WAIT 定義:

TIME_WAIT = 2* MSL,原因是 發(fā)送方數(shù)據(jù)到接受方后,接收方會(huì)返回響應(yīng),這樣一來一回正好2 倍的MSL。

Time_wait 是從客戶端接收到 FIN 后發(fā)送 ACK 開始計(jì)時(shí)的,如果在 TIME-WAIT 時(shí)間內(nèi),客戶端的 ACK 沒有傳輸?shù)椒?wù)端,客戶端又接收到了服務(wù)端重發(fā)的 FIN 報(bào)文,那 2MSL 將重新計(jì)時(shí)。

TIME_WAIT 存在意義:

防止舊連接的數(shù)據(jù)包被重新消費(fèi):上一次連接時(shí)候如果有網(wǎng)絡(luò)震蕩導(dǎo)致服務(wù)端數(shù)據(jù)在網(wǎng)絡(luò)游蕩,如果因?yàn)?time_wait 時(shí)間太短,新的連接可能會(huì)重新接受到游蕩的消息。有了延遲時(shí)間可以避免消耗游蕩的數(shù)據(jù)。

確保連接正確關(guān)閉:TIME-WAIT 作用是等待足夠的時(shí)間以確保最后的 ACK 能讓被動(dòng)關(guān)閉方接收,從而幫助其正常關(guān)閉。

TIME_WAIT 發(fā)生場(chǎng)景:

在高并發(fā)短連接的 TCP 服務(wù)器上,當(dāng)服務(wù)器處理完請(qǐng)求后立刻主動(dòng)正常關(guān)閉連接。這個(gè)場(chǎng)景下會(huì)出現(xiàn)大量 socket 處于 TIME_WAIT 狀態(tài)。如果客戶端的并發(fā)量持續(xù)很高,因?yàn)槎丝谟邢?,?nèi)存有限,會(huì)導(dǎo)致此時(shí)部分客戶端顯示連接不上。

在Linux內(nèi)核中 TIME_WAIT = 60秒。

避免 TIME_WAIT 過多:

  • 取消短連接,改用長(zhǎng)連接方式,
  • 設(shè)定閾值,一旦超過閾值系統(tǒng)會(huì)將所有time_wait 連接重置。
  • 修改客戶端程序代碼。

3.2.12 TCP 如何保證數(shù)據(jù)傳輸可靠

  • 校驗(yàn)和:發(fā)送跟接受數(shù)據(jù)都會(huì)進(jìn)行檢驗(yàn)的,如果不一致,那么傳輸有誤。
  • 確認(rèn)應(yīng)答序列號(hào):TCP進(jìn)行傳輸時(shí)數(shù)據(jù)都進(jìn)行了編號(hào),每次接收方返回ACK都有確認(rèn)序列號(hào)。
  • 超時(shí)重傳:如果發(fā)送方發(fā)送數(shù)據(jù)一段時(shí)間后沒有收到ACK,那么就重發(fā)數(shù)據(jù)。并且自帶去重功能。
  • 連接管理:三次握手和四次揮手的過程。
  • 流量控制:TCP協(xié)議報(bào)頭包含16位的窗口大小,接收方會(huì)在返回ACK時(shí)同時(shí)把自己的即時(shí)窗口填入,發(fā)送方就根據(jù)報(bào)文中窗口的大小控制發(fā)送速度。
  • 擁塞控制:剛開始發(fā)送數(shù)據(jù)的時(shí)候,擁塞窗口是1,以后每次收到ACK,則擁塞窗口+1,然后將擁塞窗口和收到的窗口取較小值作為實(shí)際發(fā)送的窗口,如果發(fā)生超時(shí)重傳,擁塞窗口重置為1。這樣做的目的就是為了保證傳輸過程的高效性和可靠性。

3.3 UDP

UDP 為應(yīng)用程序提供了一種無需建立連接就可以發(fā)送封裝的 IP 數(shù)據(jù)包的方法,它的協(xié)議很簡(jiǎn)單,頭部只有八個(gè)字節(jié):

UDP頭部

 

  • 兩個(gè)十六位的端口號(hào):分別為源端口和目標(biāo)端口。
  • 包長(zhǎng)度:該字段 = UDP首部長(zhǎng)度 + 數(shù)據(jù)長(zhǎng)度。
  • 校驗(yàn)和:整個(gè)數(shù)據(jù)報(bào)文的檢驗(yàn)和,該字段用于發(fā)現(xiàn)頭部信息和數(shù)據(jù)中的錯(cuò)誤。

3.3.1 UDP 特點(diǎn)

UDP有不提供數(shù)據(jù)包分組、組裝和不能對(duì)數(shù)據(jù)包進(jìn)行排序的缺點(diǎn),當(dāng)報(bào)文發(fā)送之后,是無法得知其是否安全完整到達(dá)的。

1.面向無連接

UDP 不會(huì)進(jìn)行三次握手建立連接,想建立連接就建立連接,并且也只是數(shù)據(jù)報(bào)文的搬運(yùn)工,不會(huì)對(duì)數(shù)據(jù)報(bào)文進(jìn)行任何拆分和拼接操作。

在發(fā)送端,應(yīng)用層將數(shù)據(jù)傳遞給傳輸層的 UDP 協(xié)議,UDP 只會(huì)給數(shù)據(jù)增加一個(gè) UDP 頭標(biāo)識(shí)下是 UDP 協(xié)議,然后就傳遞給網(wǎng)絡(luò)層了。

在接收端,網(wǎng)絡(luò)層將數(shù)據(jù)傳遞給傳輸層,UDP 只去除 IP 報(bào)文頭就傳遞給應(yīng)用層,不會(huì)任何拼接操作

2.有單播、多播、廣播的功能

UDP 不止支持一對(duì)一的傳輸方式,同樣支持一對(duì)多,多對(duì)多,多對(duì)一的方式,也就是說 UDP 提供了單播,多播,廣播的功能。

3.UDP面向報(bào)文

發(fā)送方的UDP對(duì)應(yīng)用程序交下來的報(bào)文,在添加首部后就向下交付IP層。UDP對(duì)應(yīng)用層交下來的報(bào)文,既不合并,也不拆分,而是保留這些報(bào)文的邊界。因此應(yīng)用程序必須選擇合適大小的報(bào)文

4.不可靠性

不可靠性體現(xiàn)在無連接上,通信都不需要建立連接,想發(fā)就發(fā),這樣的情況肯定不可靠。

收到什么數(shù)據(jù)就傳遞什么數(shù)據(jù),并且也不會(huì)備份數(shù)據(jù),發(fā)送數(shù)據(jù)也不會(huì)關(guān)心對(duì)方是否已經(jīng)正確接收到數(shù)據(jù)了。

沒有擁塞控制,一直會(huì)以恒定的速度發(fā)送數(shù)據(jù)。網(wǎng)絡(luò)不好可能導(dǎo)致丟包,在某些實(shí)時(shí)性要求高的場(chǎng)景,比如視頻電話就需要使用 UDP。

5.頭部開銷小

UDP 的頭部開銷小,只有八字節(jié),相比 TCP 的至少二十字節(jié)要少得多,在傳輸數(shù)據(jù)報(bào)文時(shí)是很高效的

3.3.2 TCP 跟 UDP 對(duì)比

 

3.3.3 TCP UDP 共有端口

你可能經(jīng)常被問到,TCP 和 UDP 為何可以共用同一端口?這是因?yàn)閺木W(wǎng)絡(luò)層的角度來看,它是不知道端口這個(gè)概念的,TCP/UDP 都是包裹在 IP 協(xié)議內(nèi)的,IP 協(xié)議只需要知道 IP 對(duì)應(yīng)的硬件地址就可以把遠(yuǎn)端的網(wǎng)絡(luò)包發(fā)送到目的主機(jī)上。

端口這個(gè)概念是由操作系統(tǒng)劃分的。因?yàn)閮?nèi)核不可能把所有網(wǎng)絡(luò)數(shù)據(jù)都發(fā)送給所有的進(jìn)程,所以為了區(qū)分哪些數(shù)據(jù)該劃分給哪些進(jìn)程,便在傳輸層的協(xié)議中定義了端口。而TCP和UDP協(xié)議中的端口號(hào)占位都是16位,所以操作系統(tǒng)能綁定的端口也就只有65535個(gè)。

如果你查看 C 語言有關(guān) Socket 編程中的 socket 跟 bind 函數(shù)你會(huì)發(fā)現(xiàn),系統(tǒng)是以 協(xié)議 + ip + 端口來綁定端口的,所以不同協(xié)議相同的ip和端口也是可以綁定成功的。

4 TCP 進(jìn)階

4.1 TCP 重傳機(jī)制

為保證數(shù)據(jù)安全到達(dá)接受端,TCP引入了超時(shí)重傳、快速重傳、SACK、D-SACK。

4.1.1 超時(shí)重傳

以時(shí)間為基準(zhǔn),在發(fā)送數(shù)據(jù)時(shí)設(shè)置個(gè)定時(shí)器,如果期限內(nèi)沒收到接受者的ACK就會(huì)重新發(fā)送數(shù)據(jù),一般數(shù)據(jù)包丟失或確認(rèn)應(yīng)答丟失會(huì)導(dǎo)致超時(shí)重傳,這里先普及兩個(gè)跟時(shí)間相關(guān)的參數(shù)跟一些規(guī)則。

  • RTT:Round-Trip Time 往返時(shí)間,指的是數(shù)據(jù)從發(fā)送到接受的耗時(shí)時(shí)間。
  • RTO :Retransmission Timeout 超時(shí)重傳時(shí)間。
  • 動(dòng)態(tài):RTT 收到網(wǎng)絡(luò)波動(dòng)是動(dòng)態(tài)變化的,同理RTO也是動(dòng)態(tài)變化的。
  • RTO翻倍:每遇到一次超時(shí)重傳,系統(tǒng)都會(huì)將下一次RTO翻倍。

RTO跟RTT

 

RTT跟RTO之間的關(guān)系十分微妙。

  1. RTO 較小時(shí)可能導(dǎo)致數(shù)據(jù)本來就沒丟失只是還沒被響應(yīng), 又重發(fā)會(huì)增加網(wǎng)絡(luò)擁塞,導(dǎo)致更多的超時(shí)重發(fā)。
  2. RTO較大時(shí)候可能導(dǎo)致數(shù)據(jù)已經(jīng)丟了好久才重發(fā)數(shù)據(jù)。

所以離線情況下 RTO 稍微大于 RTT是最好的。具體規(guī)則有興趣的可自行百度。

4.1.2 快速重傳

TCP有累計(jì)確認(rèn)機(jī)制,當(dāng)接收端收到比期望序號(hào)大的報(bào)文段時(shí),便會(huì)重復(fù)發(fā)送最近一次確認(rèn)的報(bào)文段的確認(rèn)信號(hào),我們稱之為冗余ACK(duplicate ACK)。

如圖所示,報(bào)文段1成功接收并被確認(rèn)ACK 2,接收端的期待序號(hào)為2,當(dāng)報(bào)文段2丟失,報(bào)文段3失序到來,與接收端的期望不匹配,接收端重復(fù)發(fā)送冗余ACK 2。

快速重傳機(jī)制

 

發(fā)送端如果在超時(shí)重傳定時(shí)器溢出之前,接收到連續(xù)的三個(gè)重復(fù)冗余ACK(其實(shí)是收到4個(gè)同樣的ACK,第一個(gè)是正常的,后三個(gè)才是冗余的),發(fā)送端便知曉哪個(gè)報(bào)文段在傳輸過程中丟失了,于是重發(fā)該報(bào)文段,不需要等待超時(shí)重傳定時(shí)器溢出,最后客戶端收到 2,因?yàn)?45已經(jīng)回復(fù)過了,返回ACK6。

為啥是3次呢? 你要明白發(fā)送端即使按序發(fā)送,接收端也是會(huì)出現(xiàn)亂序的。亂序也會(huì)造成冗余ACK發(fā)送,那冗余ACK是亂序?qū)е逻€是丟包導(dǎo)致呢?經(jīng)過權(quán)衡把3次冗余ACK作為判定丟失的準(zhǔn)則其本身就是估計(jì)值。

 

 


數(shù)據(jù)接收情況

 

 

A為發(fā)送端,B為接收端,A的待發(fā)報(bào)文段序號(hào)為 【N-1,N,N+1,N+2】,假設(shè)報(bào)文段N-1成功到達(dá)。

  1. 在沒丟失的情況下,有40%的可能出現(xiàn)3次冗余ACK,在亂序的情況下必定是2次冗余ACK。
  2. 在丟失的情況下,必定出現(xiàn)3次冗余ACK。

基于這樣的概率,選定3次冗余ACK作為閾值也算是合理的。實(shí)際抓包時(shí)大多數(shù)的快速重傳都會(huì)在大于3次冗余ACK后發(fā)生。

快速重傳解決了超時(shí)問題,可是重傳時(shí)是重傳之前的一個(gè),還是重傳所有它是定不了的。

4.1.3 SACK

既然快速重傳搞不定,就用 Selective Acknowledgment 選擇性確認(rèn),原理也很簡(jiǎn)單,服務(wù)端給客戶端回復(fù)的時(shí)候多加個(gè)字段SACK,SACK的內(nèi)容就是告知發(fā)送端服務(wù)端收到了哪些。這樣服務(wù)端可以根據(jù)收到的信息選擇性發(fā)送丟失的包。

4.1.4 D-SACK

DSACK是在SACK的基礎(chǔ)上做了一些擴(kuò)展,主要用于對(duì)收到的重復(fù)報(bào)文進(jìn)行了處理。DSACK同樣使用了與SACK一樣的報(bào)文格式。核心關(guān)注點(diǎn)是發(fā)送的時(shí)候出問題了還是回復(fù)的時(shí)候出問題了。

如果發(fā)送端發(fā)送數(shù)據(jù)A延時(shí)而觸發(fā)了快速重傳機(jī)制,快速重傳機(jī)制發(fā)送過來的信息新A,然后老A又到了,接收端會(huì)回復(fù)SACK 意思是網(wǎng)絡(luò)震蕩導(dǎo)致的。

如果服務(wù)端的ACK 客戶端沒收到,客戶端重發(fā)的時(shí)候,服務(wù)端會(huì)回復(fù)SACK,意思就是你的數(shù)據(jù)發(fā)送重復(fù)了。

4.2 TCP 滑動(dòng)窗口

如果沒有滑動(dòng)窗口的機(jī)制:傳輸N份文件,就需要等待N次應(yīng)答時(shí)間。

總的傳輸時(shí)間 = N份傳輸時(shí)間 + N份應(yīng)答傳輸時(shí)間。

保證可靠性的前提下TCP 引入了窗口概念,滑動(dòng)窗口可以讓我們進(jìn)一步提高傳輸效率。在窗口內(nèi)的數(shù)據(jù)無需等待確認(rèn)應(yīng)答就可以繼續(xù)發(fā)送數(shù)據(jù)。窗口的本質(zhì)是OS開辟的一個(gè)緩存空間,然后進(jìn)行批量傳輸,只要接收方?jīng)]確認(rèn)應(yīng)答那么緩存中會(huì)一直存在。

總的傳輸時(shí)間 = N分?jǐn)?shù)據(jù)傳輸時(shí)間疊加成一份時(shí)間,N份應(yīng)答傳輸時(shí)間,重疊成一份時(shí)間

 

 


窗口大小為4000字節(jié)

 

 

窗口大小一般是接收方來決定的,接收方會(huì)告知發(fā)送方自己有多少緩存可接受數(shù)據(jù),如果超過這個(gè)數(shù)據(jù)量接收方就無法接收了。

4.2.1 發(fā)送滑動(dòng)窗口

滑動(dòng)窗口

 

在一的狀態(tài)下發(fā)送方收到一個(gè)請(qǐng)求序列號(hào)2001的確認(rèn)應(yīng)答ACK,則2001前數(shù)據(jù)被標(biāo)記為傳輸完畢,系統(tǒng)會(huì)進(jìn)行窗口滑動(dòng)變?yōu)槎臉幼印?/p>

  1. 窗口左邊是已經(jīng)發(fā)送并且受到服務(wù)器的ACK的數(shù)據(jù),這些數(shù)據(jù)可以從緩存刪除。
  2. 窗口內(nèi)的數(shù)據(jù)其實(shí)也分為兩類,一類是發(fā)送還沒接收到ACK的,一類是還未發(fā)送的。在收到整個(gè)窗口的確認(rèn)應(yīng)答ACK之前,如果數(shù)據(jù)有丟失,發(fā)送端仍然需要重傳。所以發(fā)送端需要有緩存保留可能被重傳的數(shù)據(jù),直到收到服務(wù)端ACK。
  3. 收到服務(wù)端ACK后,發(fā)送端會(huì)將窗口滑動(dòng)到確認(rèn)應(yīng)答中的序列號(hào)的位置。這樣可以順序地將多個(gè)段同時(shí)發(fā)送提高通信性能。這種機(jī)制也別稱為滑動(dòng)窗口控制。
  4. 窗口模式下發(fā)送方也會(huì)根據(jù)接收方的能力來進(jìn)行發(fā)送數(shù)據(jù)來進(jìn)行流量控制。

4.2.2 窗口數(shù)據(jù)丟失

這里的數(shù)據(jù)丟失其實(shí)跟前面說到的重傳機(jī)制類似,主要分為兩種

接收端收到信息但是返回ACK失敗了:如果丟失ACK,不需要做任何處理,如3001這個(gè)ACK丟了,但是4001ACK卻已經(jīng)發(fā)送給主機(jī)A,說明2001~3000這個(gè)數(shù)據(jù)也順利到達(dá),3001ACK丟了無所謂,只要當(dāng)前序號(hào)開始,就說明之前的數(shù)據(jù)已經(jīng)正確傳輸?shù)竭_(dá)主機(jī)B

 


收到數(shù)據(jù)但ACK丟失

 

 

發(fā)送端發(fā)送數(shù)據(jù)中途數(shù)據(jù)丟失了:如下圖1001-2000數(shù)據(jù)包丟了,而2001-3000,3001-4000都順利到達(dá),此時(shí)接收方反饋的ACK確認(rèn)序號(hào)始終是1001,發(fā)送方如果發(fā)現(xiàn)接收方連續(xù)發(fā)送ACK都是1001,接收方就明白1001-2000這個(gè)數(shù)據(jù)丟包,就會(huì)重新傳送,當(dāng)接收方重新收到丟失的1001-2000數(shù)據(jù)后,直接返回ACK4001,因?yàn)?001-4000已經(jīng)接受過放到緩存區(qū)了,接下來ACK直接從4001開始。

 

 


發(fā)送時(shí)丟失

 

 

4.3 擁塞控制

前面說到的流量控制只是單純的對(duì)于發(fā)送方跟接受方而已,但是我們要知道網(wǎng)絡(luò)一般都是公用的,別的服務(wù)器也可以能將網(wǎng)絡(luò)搞阻塞,因?yàn)樽枞麑?dǎo)致重發(fā),然后重發(fā)導(dǎo)致更阻塞,最后陷入惡性循環(huán)。

為了控制發(fā)送方的數(shù)據(jù)量避免數(shù)據(jù)阻塞整個(gè)網(wǎng)絡(luò),發(fā)送方維護(hù)著一個(gè)叫擁塞窗口的東西,前面說到過發(fā)送窗口跟接受窗口,現(xiàn)在由于有了擁塞窗口,此時(shí) 發(fā)送窗口swnd = min(擁塞窗口cwnd,接受窗口rwnd)。擁塞窗口的大小是動(dòng)態(tài)變化的,當(dāng)網(wǎng)絡(luò)沒阻塞就會(huì)變大,網(wǎng)絡(luò)中有阻塞就會(huì)變小。判斷阻塞的依據(jù)就是如果發(fā)送方在指定時(shí)間內(nèi)沒收到數(shù)據(jù)那就是阻塞了。

擁塞控制主要通過慢開始,快重傳,快恢復(fù)和避免擁塞來實(shí)現(xiàn)的。

4.3.1 慢開始

TCP建立連接后系統(tǒng)有個(gè)慢啟動(dòng)的過程,意思就是一點(diǎn)一點(diǎn)的提高發(fā)送數(shù)據(jù)包的數(shù)量,慢啟動(dòng)的原則就是當(dāng)發(fā)送方每收到一個(gè) ACK,擁塞窗口 cwnd 的大小就會(huì)加 1。有一個(gè)叫慢啟動(dòng)門限 slow start threshold 狀態(tài)變量來充當(dāng)最大值。

cwnd < ssthresh 時(shí),使用慢啟動(dòng)算法。

cwnd >= ssthresh 時(shí),使用擁塞避免算法。

4.3.2 擁塞避免算法

一般情況下 slow start threshold = 65535字節(jié),系統(tǒng)進(jìn)入擁塞避免算法后,每當(dāng)收到一個(gè) ACK 時(shí),擁塞窗口就增加 1/擁塞窗口。擁塞避免算法存在的意義就是將慢開始的那種指數(shù)增長(zhǎng)變化為線程增長(zhǎng)。

4.3.3 快重傳

進(jìn)入擁塞避免算法后的數(shù)據(jù)隨著不斷增長(zhǎng)最終會(huì)導(dǎo)致網(wǎng)絡(luò)阻塞,最終引發(fā)丟包。然后會(huì)采用前面說到的超時(shí)重傳跟快速重傳。

  • 超時(shí)重傳:ssthresh = cwnd/2 同時(shí) cwnd 重置為 1,然后重新開始慢啟動(dòng),回到了起點(diǎn)。
  • 快速重傳:cwnd = cwnd/2 同時(shí) ssthresh = cwnd 然后進(jìn)入快速恢復(fù)算法。

4.3.4 快恢復(fù)

快恢復(fù)與快重傳配合使用,當(dāng)發(fā)送方接收到連續(xù)三個(gè)重復(fù)確認(rèn)請(qǐng)求,為了避免網(wǎng)絡(luò)擁塞,執(zhí)行快速重傳(cwnd = cwnd/2 同時(shí) ssthresh = cwnd ),執(zhí)行快速恢復(fù)算法。

  • cwnd = ssthresh + 3
  • 重傳丟失的數(shù)據(jù)包
  • 收到重復(fù)ACK則 cwnd 累加 1。
  • 收到新ACK后設(shè)置 cwnd = ssthresh,進(jìn)入擁塞避免算法。

5 參考

科技哥網(wǎng)絡(luò):https://t.1yb.co/gJRx

小林網(wǎng)絡(luò):https://t.1yb.co/fQG3

TCP/IP講解:https://developer.51cto.com/art/201906/597961.htm

快速重傳:https://blog.csdn.net/whgtheone/article/details/80983882

責(zé)任編輯:武曉燕 來源: sowhat1412
相關(guān)推薦

2018-09-28 10:23:57

微軟 Windows Linux

2023-12-01 08:49:29

哨兵模式自動(dòng)恢復(fù)

2022-07-27 07:36:01

TCP可靠性

2021-05-18 08:32:33

TCPIP協(xié)議

2021-07-12 07:08:52

TCP協(xié)議面試

2020-07-06 11:53:08

TCP三次握手協(xié)議

2020-06-22 11:50:38

TCPIP協(xié)議

2020-08-31 19:19:27

TCPUDP視屏面試

2022-07-25 07:07:35

TCP客戶端服務(wù)器

2017-05-10 14:50:41

爬蟲掃描器python

2020-03-03 17:47:07

UDP TCP面試題

2019-11-26 08:24:13

TCP擁塞控制網(wǎng)絡(luò)協(xié)議

2020-12-02 06:12:27

TCPIP面試

2022-08-03 14:55:42

5G

2023-10-17 16:30:00

TCP

2021-05-14 08:34:32

UDP TCP場(chǎng)景

2015-02-26 18:09:29

WaterFall V瀑布流Dynamic Gri

2011-03-14 15:56:37

NoSQL

2021-08-13 10:28:18

IT領(lǐng)導(dǎo)者CIO業(yè)務(wù)

2023-10-28 09:07:57

TCP面試三次握手
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)