偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

面試反客為主 TCP

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

[[381851]]

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

3 傳輸層 TCP/UDP

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

3.1 DNS

3.1.1 DNS 講解

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

我們在瀏覽器地址欄中輸入的每一個地址都是一個域名,比如 www.baidu.com。域名是由.和不同級別域的域名組成。通常我們在書寫時會省略根域名,即域名結(jié)尾的.,如www.baidu.com.。由于域名是老外發(fā)明的所以從左到右范圍逐步變大且以.分割。

DNS分層

 

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

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

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

3.1.2 DNS 樣例

DNS域名解析

 

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

3.2 TCP

3.2.1 TCP 頭部講解

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

TCP頭部 + HTTP

 

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

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

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

8.ACK:表示是否前面確認號字段是否有效。只有當 ACK=1 時,前面的確認號字段才有效。TCP 規(guī)定連接建立后 ACK=1,帶 ACK 標志的TCP報文段稱為確認報文段。

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

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

11.SYN:建立連接時用來同步序號。SYN=1 說明這是一個請求建立連接或同意建立連接的報文。只有在前兩次握手中 SYN 才置為1,帶 SYN 標志的 TCP 報文段稱為同步報文段。

  • 當 SYN=1 且 ACK=0 時表示這是一個請求建立連接的報文段。
  • 當 SYN=1 且 ACK=1 時表示對方同意建立連接。

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

13.窗口大小:表示現(xiàn)在允許對方發(fā)送的數(shù)據(jù)量,告訴對方從本報文段的確認號開始允許對方發(fā)送的數(shù)據(jù)量,達到此值,需要ACK確認后才能再繼續(xù)傳送后面數(shù)據(jù)。

14.校驗和:提供額外的可靠性。

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

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

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

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

3.2.2 TCP 三次握手

TCP三次握手

 

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

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

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

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

信息傳輸大致流程

 

3.2.4 TCP 狀態(tài)查詢

服務器一般用 netstat 查看 tcp,udp 的端口和進程等相關情況。netstat -tunlp | grep 端口號

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

netstat樣例

 

3.2.5 TCP 為啥三次握手

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

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

如果還不太理解,我們用個生活常識說明下。晚上你在小區(qū)里散步,不遠處看見一位漂亮妹子迎面而來,因為路燈有點暗不能100%確認,所以要通過招手的方式來確定對方是否認識自己。

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

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

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

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

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

因為妹子連續(xù)進行了兩個動作,先是點頭微笑,然后再次招手,所以可以將這兩個動作合成一個動作,招手的同時點頭和微笑。于是這四個動作就簡化成了三個動作。

你與妹子的相識

 

3.2.6 TCP 三次握手的意義

1.避免歷史連接

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

2.同步雙方初始序列號

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

3.避免服務端資源浪費

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

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

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

3.2.8 TCP 如何避免 SYN 攻擊

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

解決方法:

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

3.2.9 TCP 四次揮手

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

TCP四次揮手

 

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

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

你跟妹子揮手離別

 

3.2.10 TCP 為什么四次揮手

其實分析下整個關閉的流程就知道為什么必須是四次揮手而不是三次揮手了。

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

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

MSL 定義:

Maximum Segment Lifetime 報文最大生存時間,意思是網(wǎng)絡傳輸?shù)膱笪脑诰W(wǎng)絡上存在的最長時間,超過這個時間報文將被丟棄。而數(shù)據(jù)之所以可以被拋棄是因為TCP層的下面的IP層有個TTL來記錄報文傳輸過程中經(jīng)過的最大路由次數(shù)。

TIME_WAIT 定義:

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

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

TIME_WAIT 存在意義:

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

確保連接正確關閉:TIME-WAIT 作用是等待足夠的時間以確保最后的 ACK 能讓被動關閉方接收,從而幫助其正常關閉。

TIME_WAIT 發(fā)生場景:

在高并發(fā)短連接的 TCP 服務器上,當服務器處理完請求后立刻主動正常關閉連接。這個場景下會出現(xiàn)大量 socket 處于 TIME_WAIT 狀態(tài)。如果客戶端的并發(fā)量持續(xù)很高,因為端口有限,內(nèi)存有限,會導致此時部分客戶端顯示連接不上。

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

避免 TIME_WAIT 過多:

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

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

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

3.3 UDP

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

UDP頭部

 

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

3.3.1 UDP 特點

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

1.面向無連接

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

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

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

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

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

3.UDP面向報文

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

4.不可靠性

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

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

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

5.頭部開銷小

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

3.3.2 TCP 跟 UDP 對比

 

3.3.3 TCP UDP 共有端口

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

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

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

4 TCP 進階

4.1 TCP 重傳機制

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

4.1.1 超時重傳

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

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

RTO跟RTT

 

RTT跟RTO之間的關系十分微妙。

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

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

4.1.2 快速重傳

TCP有累計確認機制,當接收端收到比期望序號大的報文段時,便會重復發(fā)送最近一次確認的報文段的確認信號,我們稱之為冗余ACK(duplicate ACK)。

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

快速重傳機制

 

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

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

 

 


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

 

 

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

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

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

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

4.1.3 SACK

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

4.1.4 D-SACK

DSACK是在SACK的基礎上做了一些擴展,主要用于對收到的重復報文進行了處理。DSACK同樣使用了與SACK一樣的報文格式。核心關注點是發(fā)送的時候出問題了還是回復的時候出問題了。

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

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

4.2 TCP 滑動窗口

如果沒有滑動窗口的機制:傳輸N份文件,就需要等待N次應答時間。

總的傳輸時間 = N份傳輸時間 + N份應答傳輸時間。

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

總的傳輸時間 = N分數(shù)據(jù)傳輸時間疊加成一份時間,N份應答傳輸時間,重疊成一份時間

 

 


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

 

 

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

4.2.1 發(fā)送滑動窗口

滑動窗口

 

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

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

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

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

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

 


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

 

 

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

 

 


發(fā)送時丟失

 

 

4.3 擁塞控制

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

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

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

4.3.1 慢開始

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

cwnd < ssthresh 時,使用慢啟動算法。

cwnd >= ssthresh 時,使用擁塞避免算法。

4.3.2 擁塞避免算法

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

4.3.3 快重傳

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

  • 超時重傳:ssthresh = cwnd/2 同時 cwnd 重置為 1,然后重新開始慢啟動,回到了起點。
  • 快速重傳:cwnd = cwnd/2 同時 ssthresh = cwnd 然后進入快速恢復算法。

4.3.4 快恢復

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

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

5 參考

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

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

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

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

責任編輯:武曉燕 來源: sowhat1412
相關推薦

2018-09-28 10:23:57

微軟 Windows Linux

2023-12-01 08:49:29

哨兵模式自動恢復

2022-07-27 07:36:01

TCP可靠性

2020-07-06 11:53:08

TCP三次握手協(xié)議

2020-06-22 11:50:38

TCPIP協(xié)議

2021-07-12 07:08:52

TCP協(xié)議面試

2021-05-18 08:32:33

TCPIP協(xié)議

2017-05-10 14:50:41

爬蟲掃描器python

2022-07-25 07:07:35

TCP客戶端服務器

2020-08-31 19:19:27

TCPUDP視屏面試

2022-08-03 14:55:42

5G

2020-12-02 06:12:27

TCPIP面試

2019-11-26 08:24:13

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

2020-03-03 17:47:07

UDP TCP面試題

2021-05-14 08:34:32

UDP TCP場景

2023-10-17 16:30:00

TCP

2021-08-13 10:28:18

IT領導者CIO業(yè)務

2011-03-14 15:56:37

NoSQL

2015-02-26 18:09:29

WaterFall V瀑布流Dynamic Gri

2012-12-13 13:33:48

點贊
收藏

51CTO技術棧公眾號