1.TCP和UDP的區(qū)別
TCP是面向連接的,UDP是面向無連接的;
TCP只能一對一通信,UDP支持一對一,一對多,多對一和多對多交互通信;
TCP是面向字節(jié)流的,UDP是面向報(bào)文的;
TCP是可靠傳輸,使用流量控制和擁塞控制;UDP是不可靠傳輸
TCP首部最小20字節(jié),最大60字節(jié);UDP首部僅8字節(jié)。
2.ISO七層模型及相關(guān)協(xié)議
物理層:建立、維護(hù)、斷開物理連接。
數(shù)據(jù)鏈路層:在物理層提供比特流服務(wù)的基礎(chǔ)上,建立相鄰結(jié)點(diǎn)之間的數(shù)據(jù)鏈路。
網(wǎng)絡(luò)層:進(jìn)行邏輯地址尋址,實(shí)現(xiàn)不同網(wǎng)絡(luò)之間的路徑選擇,協(xié)議有ICMP、IGMP、IP等。
傳輸層:定義傳輸數(shù)據(jù)的協(xié)議端口號,以及流量控制和差錯校驗(yàn),協(xié)議有TCP、UDP。
會話層:建立、管理、終止會話,指本地主機(jī)與遠(yuǎn)程主機(jī)正在進(jìn)行的會話。
表示層:確保一個系統(tǒng)的應(yīng)用層所發(fā)送的信息可以被另一個系統(tǒng)的應(yīng)用層讀取。
應(yīng)用層:網(wǎng)絡(luò)服務(wù)與最終用戶的一個接口,常見的協(xié)議有:HTTP、FTP、SMTP、DNS。
TCP/IP 四層模型
- 網(wǎng)絡(luò)接口層
- 網(wǎng)際層
- 傳輸層
- 應(yīng)用層
五層體系結(jié)構(gòu)
- 物理層
- 數(shù)據(jù)鏈路層
- 網(wǎng)絡(luò)層:IP網(wǎng)際協(xié)議、ARP地址轉(zhuǎn)換協(xié)議、RIP路由信息協(xié)議
- 傳輸層:TCP傳輸控制協(xié)議、UDP用戶數(shù)據(jù)報(bào)文協(xié)議
- 應(yīng)用層:HTTP超文本傳輸協(xié)議、FTP文本傳輸協(xié)議、DNS域名系統(tǒng)
3.如何理解HTTP協(xié)議是無狀態(tài)的
當(dāng)瀏覽器第一次發(fā)送請求給服務(wù)器時,服務(wù)器響應(yīng)了;
如果同個瀏覽器發(fā)起第二次請求給服務(wù)器時,它還是會響應(yīng)。但是呢,服務(wù)器不知道你就是剛才的那個瀏覽器。
簡而言之,服務(wù)器不會去記住你是誰,所以是無狀態(tài)協(xié)議。
4.簡述從瀏覽器地址欄輸入url到顯示主頁的過程
- DNS解析,查找域名對應(yīng)的IP地址。
- 與服務(wù)器通過三次握手,建立TCP連接。
- 向服務(wù)器發(fā)送HTTP請求。
- 服務(wù)器處理請求,返回網(wǎng)頁內(nèi)容。
- 瀏覽器解析并渲染頁面。
- TCP四次握手,連接結(jié)束。
5.說下 HTTP/1.0,1.1,2.0 的區(qū)別
HTTP/1.0
默認(rèn)使用短連接,每次請求都需要建立一個TCP連接。它可以設(shè)置Connection: keep-alive 這個字段,強(qiáng)制開啟長連接。
HTTP/1.1
- 默認(rèn)使用長連接,即TCP連接默認(rèn)不關(guān)閉,可以被多個請求復(fù)用。
- 分塊傳輸編碼,即服務(wù)端每產(chǎn)生一塊數(shù)據(jù),就發(fā)送一塊,用“流模式”取代“緩存模式”。
- 管道機(jī)制,即在同一個TCP連接里面,客戶端可以同時發(fā)送多個請求。
HTTP/2.0
- 二進(jìn)制協(xié)議,1.1版本的頭信息是文本(ASCII編碼),數(shù)據(jù)體可以是文本或二進(jìn)制;2.0中,頭信息和數(shù)據(jù)體都是二進(jìn)制。
- 完全多路復(fù)用,在一個連接里,客戶端和服務(wù)器都可以同時發(fā)送多個請求或響應(yīng),而且不用按照順序一一對應(yīng)。
- 報(bào)頭壓縮,HTTP協(xié)議不帶有狀態(tài),每次請求都必須帶上所有信息。HTTP/2.0引入了頭信息壓縮機(jī)制,使用gzip或compress壓縮后再發(fā)送。
- 服務(wù)端推送,允許服務(wù)器未經(jīng)請求,主動向客戶端發(fā)送資源。
6.POST和GET有哪些區(qū)別
7.HTTP 如何實(shí)現(xiàn)長連接?在什么時候會超時?
什么是HTTP的長連接?
- HTTP分為長連接和短連接,本質(zhì)上說的是TCP的長短連接。TCP連接是一個雙向的通道,它是可以保持一段時間不關(guān)閉的,因此TCP連接才具有真正的長連接和短連接這一說法。
- TCP長連接可以復(fù)用一個TCP連接,來發(fā)起多次HTTP請求,這樣就可以減少資源消耗,比如一次HTML請求,如果是短連接的話,可能還需要請求后續(xù)的JS/CSS。
如何設(shè)置長連接?
通過在請求頭和響應(yīng)頭設(shè)置Connection字段指定為keep-alive,HTTP/1.0協(xié)議支持,但默認(rèn)是關(guān)閉的,從HTTP/1.1以后,連接默認(rèn)都是長連接。
在什么時候會超時?
- HTTP一般會有httpd守護(hù)進(jìn)程,里面可以設(shè)置keep-alive timeout,當(dāng)tcp連接閑置超過這個時間就會關(guān)閉,也可以在HTTP的header里面設(shè)置超時時間。
- TCP 的keep-alive包含三個參數(shù),支持在系統(tǒng)內(nèi)核的net.ipv4里面設(shè)置;當(dāng) TCP 連接之后,閑置了tcp_keepalive_time,則會發(fā)生偵測包,如果沒有收到對方的ACK,那么會每隔 tcp_keepalive_intvl 再發(fā)一次,直到發(fā)送了tcp_keepalive_probes,就會丟棄該連接。
tcp_keepalive_probes = 5
tcp_keepalive_time = 1800
8.HTTP 與 HTTPS 的區(qū)別
HTTP 即超文本傳輸協(xié)議,是一個基于TCP/IP通信協(xié)議來傳遞明文數(shù)據(jù)的協(xié)議。HTTP會存在這幾個問題:
- 請求信息是明文傳輸,容易被竊聽截取。
- 沒有驗(yàn)證對方身份,存在被冒充的風(fēng)險(xiǎn)。
- 數(shù)據(jù)的完整性未校驗(yàn),容易被中間人篡改。
為了解決HTTP存在的問題,HTTPS出現(xiàn)啦。
HTTPS是什么?
HTTPS= HTTP+SSL/TLS,可以理解為 HTTPS 是身披 SSL(Secure Socket Layer,安全套接層)的HTTP。
它們的主要區(qū)別如下:
9.HTTPS的工作流程是怎樣的?
- HTTPS = HTTP + SSL/TLS,也就是用SSL/TLS對數(shù)據(jù)進(jìn)行加密和解密,用HTTP進(jìn)行傳輸。
- SSL,即Secure Sockets Layer(安全套接層協(xié)議),是網(wǎng)絡(luò)通信提供安全及數(shù)據(jù)完整性的一種安全協(xié)議。
- TLS,即Transport Layer Security(安全傳輸層協(xié)議),它是SSL3.0的后續(xù)版本。
- 客戶端發(fā)起HTTPS請求,連接到服務(wù)器的443端口。
- 服務(wù)器必須要有一套數(shù)字證書(證書內(nèi)容有公鑰、證書頒發(fā)機(jī)構(gòu)、失效日期等)。
- 服務(wù)器將自己的數(shù)字證書發(fā)送給客戶端(公鑰在證書里面,私鑰由服務(wù)器持有)。
- 客戶端收到數(shù)字證書之后,會驗(yàn)證證書的合法性。如果證書驗(yàn)證通過,就會生成一個隨機(jī)的對稱密鑰,用證書的公鑰加密。
- 客戶端將公鑰加密后的密鑰發(fā)送到服務(wù)器。
- 服務(wù)器接收到客戶端發(fā)來的密文密鑰之后,用自己之前保留的私鑰對其進(jìn)行非對稱解密,解密之后就得到客戶端的密鑰,然后用客戶端密鑰對返回?cái)?shù)據(jù)進(jìn)行對稱加密,這樣子傳輸?shù)臄?shù)據(jù)都是密文啦。
- 服務(wù)器將加密后的密文返回到客戶端。
- 客戶端收到后,用自己的密鑰對其進(jìn)行對稱解密,就能得到服務(wù)器返回的數(shù)據(jù)。
10.說說HTTP的狀態(tài)碼,301和302的區(qū)別?
- 301:永久重定向,表示所請求的資源已經(jīng)永久地轉(zhuǎn)移到新的位置,這包含域名的改變或者是資源路徑的改變。
- 302:臨時重定向,表示所請求的資源臨時地轉(zhuǎn)移到新的位置,一般是24到48小時以內(nèi)的轉(zhuǎn)移會用到302。
11.說說什么是數(shù)字簽名?什么是數(shù)字證書?
數(shù)字證書構(gòu)成:
- 公鑰和個人等信息,經(jīng)過Hash算法加密,形成消息摘要;將消息摘要拿到擁有公信力的認(rèn)證中心(CA),用它的私鑰對消息摘要加密,形成數(shù)字簽名。
- 公鑰和個人信息、數(shù)字簽名共同構(gòu)成數(shù)字證書。
12.對稱加密和非對稱加密有什么區(qū)別
對稱加密:指加密和解密使用同一密鑰,優(yōu)點(diǎn)是運(yùn)算速度較快,缺點(diǎn)是不能安全地將密鑰傳輸給另一方。常見的對稱加密算法有:DES、AES等。
非對稱加密:指的是加密和解密使用不同的密鑰(即公鑰和私鑰)。公鑰與私鑰是成對存在的,如果用公鑰對數(shù)據(jù)進(jìn)行加密,只有對應(yīng)的私鑰才能解密。常見的非對稱加密算法有 RSA。
13.說說 DNS 的解析過程?
DNS的解析過程如下圖:
假設(shè)你要查詢www.baidu.com的IP地址:瀏覽器 -> 本地DNS服務(wù)器 -> 根域名服務(wù)器 -> 頂級域名服務(wù)器 -> 權(quán)威域名服務(wù)器
- 首先會查找瀏覽器的緩存,看看是否能找到www.baidu.com對應(yīng)的IP地址,找到就直接返回;否則進(jìn)行下一步。
- 將請求發(fā)往本地DNS服務(wù)器,如果查找到也直接返回,否則繼續(xù)進(jìn)行下一步;
- 本地DNS服務(wù)器向根域名服務(wù)器發(fā)送請求,根域名服務(wù)器返回負(fù)責(zé).com的頂級域名服務(wù)器的列表。
- 本地DNS服務(wù)器再向其中一個頂級域名服務(wù)器發(fā)送一個請求,返回負(fù)責(zé).baidu的權(quán)威域名服務(wù)器的列表。
- 本地DNS服務(wù)器再向其中一個權(quán)威域名服務(wù)器發(fā)送一個請求,返回www.baidu.com所對應(yīng)的IP地址。
14.說說 WebSocket與socket的區(qū)別
Socket是一套標(biāo)準(zhǔn),它完成了對TCP/IP的高度封裝,屏蔽網(wǎng)絡(luò)細(xì)節(jié),以便開發(fā)者更好地進(jìn)行網(wǎng)絡(luò)編程。
Socket等于IP地址 + 端口 + 協(xié)議。
WebSocket是一個持久化的協(xié)議,它是伴隨H5而出的協(xié)議,用來解決HTTP不支持持久化連接的問題。
Socket是一個網(wǎng)絡(luò)編程的標(biāo)準(zhǔn)接口,而WebSocket則是應(yīng)用層通信協(xié)議。
15.HTTP請求的過程與原理
HTTP是一個基于TCP/IP協(xié)議來傳遞數(shù)據(jù)的超文本傳輸協(xié)議,傳輸?shù)臄?shù)據(jù)類型有HTML、圖片等。
- 客戶端進(jìn)行DNS域名解析,得到對應(yīng)的IP地址
- 根據(jù)這個IP地址,找到對應(yīng)的服務(wù)器建立TCP連接(三次握手)
- 建立TCP連接后發(fā)起HTTP請求(一個完整的http請求報(bào)文)
- 服務(wù)器響應(yīng)HTTP請求,客戶端得到html代碼
- 客戶端解析html代碼,用html代碼中的資源(如 js、css、圖片等等)渲染頁面。
- 服務(wù)器關(guān)閉TCP連接(四次揮手)
16.forward和redirect的區(qū)別?
是servlet中的兩種主要跳轉(zhuǎn)方式。forward:轉(zhuǎn)發(fā),redirect:重定向
從地址欄顯示來說
forward是服務(wù)器內(nèi)部的重定向,服務(wù)器直接訪問目標(biāo)地址,把里面的東西取出來,但是客戶端并不知道,因此用forward的話,客戶端瀏覽器的網(wǎng)址是不會發(fā)生變化的。
redirect是服務(wù)器根據(jù)邏輯,發(fā)送一個狀態(tài)碼,告訴瀏覽器重新去請求那個地址,所以地址欄顯示的是新地址。
從數(shù)據(jù)共享來說
由于在整個轉(zhuǎn)發(fā)的過程中使用的是同一個request,因此forward會將request信息帶到被重定向的jsp或servlet中使用,即可以共享數(shù)據(jù)。
redirect不能共享數(shù)據(jù)。
從運(yùn)用的地方來說
forward一般用于用戶登錄時,根據(jù)角色轉(zhuǎn)發(fā)到相應(yīng)的模塊
redirect一般用于用戶注銷登錄時返回主頁面
從本質(zhì)上來說
forward轉(zhuǎn)發(fā)是服務(wù)器上的行為,redirect重定向是客戶端的行為。
從效率上來說
forword效率高,而redirect效率低。
從請求的次數(shù)來說
forword只有一次請求,而redirect有兩次請求。
17.Session和Cookie的區(qū)別
Cookie 是保存在客戶端的一小塊文本串的數(shù)據(jù)??蛻舳讼蚍?wù)器發(fā)起請求時,服務(wù)器會向客戶端發(fā)送一個 Cookie,客戶端就把 Cookie 保存起來。下次向同一服務(wù)器再發(fā)起請求時,Cookie 就被攜帶發(fā)送到服務(wù)器。服務(wù)器可以根據(jù)這個 Cookie 判斷用戶的身份和狀態(tài)。
Session 指的是服務(wù)器和客戶端一次會話的過程。它是另一種記錄客戶端狀態(tài)的機(jī)制。不同的是 Cookie 是保存在客戶端瀏覽器中的,而 Session 是保存在服務(wù)器上的。客戶端瀏覽器在訪問服務(wù)器時,服務(wù)器會把客戶端信息以某種形式記錄在服務(wù)器上,這就是 Session。客戶端瀏覽器再次訪問時只需要從該 Session 中查找用戶的狀態(tài)。
Session 和 Cookie 到底有什么不同呢?
Session 和 Cookie 有什么關(guān)聯(lián)呢?
可以使用 Cookie 記錄 Session 的唯一標(biāo)識
用戶第一次請求服務(wù)器時,服務(wù)器根據(jù)用戶提交的信息,創(chuàng)建對應(yīng)的Session,請求返回時將此Session的唯一標(biāo)識信息SessionID返回給瀏覽器,瀏覽器會將此SessionID信息存入Cookie中,同時Cookie記錄此SessionID是屬于哪個域名的。
當(dāng)用戶第二次訪問服務(wù)器時,請求會自動判斷此域名下是否存在Cookie信息,如果存在,則自動將Cookie信息也發(fā)送給服務(wù)器,服務(wù)器會從Cookie中獲取SessionID,再根據(jù) SessionID 查找對應(yīng)的 Session 信息,如果沒有找到則說明用戶沒有登錄或者登錄失效,如果找到則證明用戶已經(jīng)登錄可執(zhí)行后面的操作。
分布式環(huán)境下 Session 該怎么處理呢?
分布式環(huán)境下,客戶端請求經(jīng)過負(fù)載均衡,可能會分配到不同的服務(wù)器上,假如一個用戶的請求兩次沒有落到同一臺服務(wù)器上,那么在新的服務(wù)器上就沒有記錄該用戶狀態(tài)對應(yīng)的 Session。
可以使用 Redis 等分布式緩存來存儲 Session,保證在多臺服務(wù)器間共享。
客戶端如果無法使用 Cookie 怎么辦呢?
有可能客戶端無法使用 Cookie,比如瀏覽器禁用 Cookie,或者客戶端是 安卓、IOS 設(shè)備等。
這時候怎么辦呢?SessionID 怎么存呢?怎么傳給服務(wù)器呢?
首先是 SessionID 的存儲,可以使用客戶端的本地存儲,比如瀏覽器的 sessionStorage。
接下來要怎么傳呢?
- 拼接到 URL:直接把 SessionID 作為 URL 的請求參數(shù)。
- 放到請求頭:把 SessionID 放到請求頭里面,比較常用。
18.詳細(xì)說一下 TCP 的三次握手機(jī)制
TCP 三次握手過程:
最開始,客戶端和服務(wù)端都處于 CLOSE(關(guān)閉)狀態(tài),服務(wù)端監(jiān)聽客戶端的請求,進(jìn)入 LISTEN(監(jiān)聽) 狀態(tài)。
客戶端發(fā)送連接請求,進(jìn)行第一次握手(同步位 SYN=1,序號字段 seq=x),發(fā)送完畢后,客戶端就進(jìn)入 SYN_SENT(同步已發(fā)送) 狀態(tài)。
服務(wù)端確認(rèn)連接,進(jìn)行第二次握手(同步位 SYN=1,確認(rèn)位 ACK=1,序號字段 seq=y,確認(rèn)號字段 ack=x+1), 發(fā)送完畢后,服務(wù)端就進(jìn)入 SYN_RCV(同步已接收) 狀態(tài)。
客戶端收到服務(wù)端的確認(rèn)后,再次向服務(wù)端確認(rèn),進(jìn)行第三次握手(確認(rèn)位 ACK=1,確認(rèn)號字段 ack=y+1),發(fā)送完畢后,客戶端就進(jìn)入 ESTABLISHED(連接已建立) 狀態(tài),當(dāng)服務(wù)端接收到這個包時,也進(jìn)入 ESTABLISHED(連接已建立) 狀態(tài)。
需要C/C++ Linux服務(wù)器架構(gòu)師學(xué)習(xí)資料加qun812855908獲?。?a href="http://ttokpm.com/soft/special/" target="_blank">資料包括C/C++,Linux,golang技術(shù),Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協(xié)程,DPDK,ffmpeg等),免費(fèi)分享
19.TCP 握手為什么是三次,為什么不能是兩次?不能是四次?
為什么不能是兩次?
防止已失效的連接請求報(bào)文段突然又傳到服務(wù)端,因而產(chǎn)生錯誤
客戶端發(fā)送出去的第一個連接請求報(bào)文段并沒有丟失,而是因?yàn)槟承┪粗蛟谀硞€網(wǎng)絡(luò)節(jié)點(diǎn)上發(fā)生滯留,導(dǎo)致延遲到連接釋放以后的某個時間點(diǎn)才到達(dá)服務(wù)端。
本來這是一個早已失效的報(bào)文段,但是服務(wù)端收到此失效的報(bào)文段后,會誤認(rèn)為這是客戶端再次發(fā)起的一個新的連接請求,于是服務(wù)端向客戶端又發(fā)出確認(rèn)報(bào)文,表示同意建立連接。
如果不采用 “三次握手”,那么只要服務(wù)端發(fā)出確認(rèn)報(bào)文后就會認(rèn)為新的連接已經(jīng)建立了,但是客戶端并沒有發(fā)出建立連接的請求,因此不會向服務(wù)端發(fā)送數(shù)據(jù),服務(wù)端沒有收到數(shù)據(jù)就會一直等待,這樣服務(wù)端就會白白浪費(fèi)掉很多資源。
所以我們需要 “第三次握手” 來確認(rèn)這個過程:
通過第三次握手的數(shù)據(jù)來告訴服務(wù)端,客戶端有沒有收到服務(wù)端 “第二次握手” 時傳過去的數(shù)據(jù),以及這個連接的序號是不是有效的。
若發(fā)送的這個數(shù)據(jù)是 “收到且沒有問題” 的信息,服務(wù)端接收后就可以正常建立 TCP 連接,否則建立 TCP 連接失敗,服務(wù)器關(guān)閉連接端口。由此減少服務(wù)器開銷和接收到失效請求時發(fā)生的錯誤。
為什么不是四次?
簡單來說,就是三次握手已經(jīng)足夠創(chuàng)建可靠的連接,沒有必要再多一次握手導(dǎo)致花費(fèi)更多的時間在建立連接上。
20.三次握手中每一次沒收到報(bào)文會發(fā)生什么情況?
第一次握手服務(wù)端未收到 SYN 報(bào)文
服務(wù)端不會進(jìn)行任何的動作,而客戶端由于一段時間內(nèi)沒有收到服務(wù)端發(fā)來的確認(rèn)報(bào)文,等待一段時間后會重新發(fā)送 SYN 報(bào)文,
如果仍然沒有回應(yīng),會重復(fù)這個過程,直到發(fā)送次數(shù)超過最大重傳次數(shù),就會返回連接建立失敗。
第二次握手客戶端未收到服務(wù)端響應(yīng)的 ACK 報(bào)文
因?yàn)榈诙挝帐质前瑢蛻舳说谝淮挝帐值?ACK 確認(rèn)報(bào)文,所以如果客戶端遲遲沒有收到第二次握手,那么客戶端就會覺得可能是自己的 SYN 報(bào)文(第一次握手)丟失了,于是客戶端就會觸發(fā)超時重傳機(jī)制,重傳 SYN 報(bào)文。
然后,因?yàn)榈诙挝帐质前?wù)端的 SYN 報(bào)文,所以當(dāng)客戶端收到后,需要給服務(wù)端發(fā)送 ACK 確認(rèn)報(bào)文(第三次握手),服務(wù)端才會認(rèn)為該 SYN 報(bào)文被客戶端收到了。
那么,如果第二次握手丟失了,服務(wù)端就收不到第三次握手,于是服務(wù)端這邊會觸發(fā)超時重傳機(jī)制,重傳 SYN-ACK 報(bào)文。
第三次握手服務(wù)端未收到客戶端發(fā)送過來的 ACK 報(bào)文
客戶端收到服務(wù)端的 SYN-ACK 報(bào)文后,就會給服務(wù)端發(fā)送一個 ACK 報(bào)文,也就是第三次握手,此時客戶端進(jìn)入到 ESTABLISH(連接已建立) 狀態(tài)。
因?yàn)檫@個第三次握手的 ACK 是對第二次握手的 SYN 的確認(rèn)報(bào)文,所以當(dāng)?shù)谌挝帐謥G失了,如果服務(wù)端那一方遲遲收不到這個確認(rèn)報(bào)文,就會觸發(fā)超時重傳機(jī)制,重傳 SYN-ACK 報(bào)文,直到收到第三次握手,或者達(dá)到最大重傳次數(shù)。
21.第二次握手傳回了 ACK,為什么還要傳回 SYN?
ACK 是為了告訴客戶端傳來的數(shù)據(jù)已經(jīng)接收無誤。
而傳回 SYN 是為了告訴客戶端,服務(wù)端響應(yīng)的確實(shí)是客戶端發(fā)送的報(bào)文。
22.第三次握手可以攜帶數(shù)據(jù)嗎?
第三次握手是可以攜帶數(shù)據(jù)的。
此時客戶端已經(jīng)處于連接已建立狀態(tài)。對于客戶端來說,它已經(jīng)建立連接成功了,并且確認(rèn)服務(wù)端的接收和發(fā)送能力是正常的。
第一次握手不能攜帶數(shù)據(jù)是出于安全的考慮,因?yàn)槿绻试S攜帶數(shù)據(jù),攻擊者每次在 SYN 報(bào)文中攜帶大量數(shù)據(jù),就會導(dǎo)致服務(wù)端消耗更多的時間和空間去處理這些報(bào)文,會造成CPU和內(nèi)存的消耗。
23.說說 TCP 四次揮手的過程?
- 數(shù)據(jù)傳輸結(jié)束后,通信雙方都可以主動發(fā)起斷開連接請求,這里假定客戶端發(fā)起。
- 客戶端發(fā)送釋放連接報(bào)文,進(jìn)行第一次揮手(FIN=1,ACK=1,seq=u,ack=v),發(fā)送完畢后,客戶端進(jìn)入 FIN_WAIT_1(終止等待1) 狀態(tài)。
- 服務(wù)端發(fā)送確認(rèn)報(bào)文,進(jìn)行第二次揮手(ACK=1,seq =v,ack=u+1),發(fā)送完畢后,服務(wù)端進(jìn)入 CLOSE_WAIT(關(guān)閉等待) 狀態(tài),客戶端收到這個確認(rèn)包后,進(jìn)入 FIN_WAIT_2(終止等待2) 狀態(tài)。
- 服務(wù)端發(fā)送釋放連接報(bào)文,進(jìn)行第三次揮手(FIN=1,ACK1,seq=w,ack=u+1),發(fā)送完畢后,服務(wù)端進(jìn)入LAST_ACK(最后確認(rèn)) 狀態(tài),等待來自客戶端的最后一個 ACK 報(bào)文。
- 客戶端發(fā)送確認(rèn)報(bào)文,進(jìn)行第四次揮手(ACK=1,seq=u+1,ack=w+1),客戶端收到來自服務(wù)端的關(guān)閉請求,發(fā)送一個確認(rèn)包,并進(jìn)入 TIME_WAIT(時間等待) 狀態(tài),服務(wù)端接收到這個確認(rèn)包后,關(guān)閉連接,進(jìn)入 CLOSED(關(guān)閉) 狀態(tài)。
- 客戶端再經(jīng)過 2MSL 后,也進(jìn)入 CLOSED(關(guān)閉) 狀態(tài)。
客戶端在發(fā)送完最后一個確認(rèn)報(bào)文后,為什么不直接進(jìn)入關(guān)閉狀態(tài) ? 而是要進(jìn)入時間等待狀態(tài),2MSL 后才進(jìn)入關(guān)閉狀態(tài),這是否有必要呢 ?
服務(wù)端發(fā)送TCP連接釋放報(bào)文段后進(jìn)入最后確認(rèn)狀態(tài)。
客戶端收到該報(bào)文段后,發(fā)送普通的TCP確認(rèn)報(bào)文段,并進(jìn)入關(guān)閉狀態(tài)而不是時間等待狀態(tài)。然而,該TCP確認(rèn)報(bào)文段丟失了。
這必然會造成服務(wù)端對之前所發(fā)送的TCP連接釋放報(bào)文段的超時重傳,并仍處于最后確認(rèn)狀態(tài)。重傳的TCP連接釋放報(bào)文段到達(dá)客戶端,由于客戶端處于關(guān)閉狀態(tài),因此不理睬該報(bào)文段,這必然會造成服務(wù)端反復(fù)重傳TCP連接釋放報(bào)文段,并一直處于最后確認(rèn)狀態(tài)而無法進(jìn)入關(guān)閉狀態(tài)。
因此時間等待狀態(tài)以及處于該狀態(tài)2MSL時長,可以確保服務(wù)端可以收到最后一個TCP確認(rèn)報(bào)文段而進(jìn)入關(guān)閉狀態(tài)。
另外,客戶端在發(fā)送完最后一個TCP確認(rèn)報(bào)文段后,再經(jīng)過2MSL時長,就可以使本次連接持續(xù)時間內(nèi)所產(chǎn)生的所有報(bào)文段都從網(wǎng)絡(luò)中消失,這樣就可以使下一個新的TCP連接中,不會出現(xiàn)舊連接中的報(bào)文段。
為什么等待時間是2MSL?
MSL 是報(bào)?最??存時間,它是任何報(bào)?在?絡(luò)上存在的最?時間,超過這個時間報(bào)?將被丟棄。
TIME_WAIT 等待 2 倍的 MSL,是因?yàn)?絡(luò)中可能存在來?發(fā)送?的數(shù)據(jù)包,當(dāng)這些發(fā)送?的數(shù)據(jù)包被接收?處理后?會向?qū)?發(fā)送響應(yīng),所以?來?回需要等待 2 倍的時間。
?如服務(wù)端如果沒有收到客戶端發(fā)送的TCP確認(rèn)報(bào)文段,就會觸發(fā)超時重傳,重新發(fā)送TCP連接釋放報(bào)文段,客戶端收到后,會重發(fā)TCP確認(rèn)報(bào)文段給服務(wù)端, ?來?去正好 2 個 MSL。
24.TCP 揮手為什么需要四次呢?
再來回顧下四次揮手雙方發(fā) FIN 包的過程,就能理解為什么需要四次了。
關(guān)閉連接時,客戶端向服務(wù)端發(fā)送 FIN 報(bào)文,僅僅表示客戶端不再發(fā)送數(shù)據(jù)了但是還能接收數(shù)據(jù)。
服務(wù)端收到客戶端的 FIN 報(bào)文后,先返回一個 ACK 確認(rèn)報(bào)文;而服務(wù)端可能還有數(shù)據(jù)需要處理和發(fā)送,等服務(wù)端不再發(fā)送數(shù)據(jù)了,再發(fā)送 FIN 報(bào)文給客戶端來表示同意現(xiàn)在關(guān)閉連接。
從上面的過程可知,服務(wù)端通常需要等待完成數(shù)據(jù)的發(fā)送和處理,所以服務(wù)端的 ACK 和 FIN 一般都會分開發(fā)送,從而導(dǎo)致比三次握手多了一次。
25.TCP ?;钣?jì)時器有什么用?
除了時間等待計(jì)時器外,TCP 還有一個?;钣?jì)時器(keepalive timer)。
設(shè)想這樣的場景:
TCP 雙方已經(jīng)建立了連接,后來,客戶端的主機(jī)突然出現(xiàn)了故障。顯然,服務(wù)端以后就不能再收到客戶端發(fā)來的數(shù)據(jù)。因此,應(yīng)當(dāng)有措施使服務(wù)端不要再白白等待下去。這就需要使用保活計(jì)時器了。
服務(wù)端每收到一次客戶端的數(shù)據(jù),就重新設(shè)置并啟動?;钣?jì)時器(2小時定時)。若定時周期內(nèi)都沒有收到客戶端發(fā)來的數(shù)據(jù),服務(wù)端就發(fā)送一個探測報(bào)文段,以后每隔 75 秒鐘發(fā)送一次。若連續(xù)發(fā)送 10 個探測報(bào)文段后仍然無客戶端的響應(yīng),服務(wù)端就認(rèn)為客戶端出了故障,接著就關(guān)閉這個連接。
26.CLOSE-WAIT 的狀態(tài)和意義?
服務(wù)端收到客戶端關(guān)閉連接的請求并確認(rèn)之后,就會進(jìn)入 CLOSE-WAIT 狀態(tài)。
此時服務(wù)端可能還有一些數(shù)據(jù)沒有傳輸完成,因此不能立即關(guān)閉連接,而 CLOSE-WAIT 狀態(tài)就是為了保證服務(wù)端在關(guān)閉連接之前將待發(fā)送的數(shù)據(jù)處理完。
27.說說 TCP 報(bào)文首部有哪些字段?
16位端口號:源端口號,標(biāo)識發(fā)送該 TCP 報(bào)文段的應(yīng)用進(jìn)程;目的端口號,標(biāo)識接收該 TCP 報(bào)文段的應(yīng)用進(jìn)程。
32位序號:指出本 TCP 報(bào)文段數(shù)據(jù)載荷的第一個字節(jié)的序號。32位序號:指出本 TCP 報(bào)文段數(shù)據(jù)載荷的第一個字節(jié)的序號。
32位確認(rèn)號:指出期望收到對方下一個 TCP 報(bào)文段的數(shù)據(jù)載荷的第一個字節(jié)的序號,同時也是對之前收到的所有數(shù)據(jù)的確認(rèn)。若確認(rèn)號 = n,則表明到序號 n-1 為止的所有數(shù)據(jù)都已正確接收,期望收到序號為 n 的數(shù)據(jù)。
4位頭部長度:指出 TCP 報(bào)文段的首部長度。
6位標(biāo)志位:
- 確認(rèn)標(biāo)志位ACK:取值為1時確認(rèn)號字段才有效,取值為0時確認(rèn)號字段無效。TCP 規(guī)定,在連接建立后所有傳送的 TCP 報(bào)文段都必須把 ACK 置為1。
- 同步標(biāo)志位SYN:在 TCP 連接建立時用來同步序號。
- 終止標(biāo)志位FIN:用來釋放 TCP 連接。
16位窗口大?。?/p>
- 指出發(fā)送本報(bào)文段的一方的接收窗口。
- 窗口值作為接收方讓發(fā)送方設(shè)置其發(fā)送窗口的依據(jù)。
- 這是以接收方的接收能力來控制發(fā)送方的發(fā)送能力,稱為流量控制。
- 發(fā)送窗口的大小還取決于擁塞窗口的大小,也就是應(yīng)該從接收窗口和擁塞窗口中取小者。
16位校驗(yàn)和:用來檢查整個 TCP 報(bào)文段在傳輸過程中是否出現(xiàn)了誤碼。
16位緊急指針:當(dāng)發(fā)送方有緊急數(shù)據(jù)時,可將緊急數(shù)據(jù)插隊(duì)到發(fā)送緩存的最前面,并立刻封裝到一個 TCP 報(bào)文段中進(jìn)行發(fā)送。緊急指針會指出本報(bào)文段的數(shù)據(jù)載荷部分包含了多長的緊急數(shù)據(jù),緊急數(shù)據(jù)之后是普通數(shù)據(jù)。
28.TCP 是如何保證可靠性的?
TCP主要提供了 連接管理、校驗(yàn)和、序列號/確認(rèn)應(yīng)答、流量控制、最大消息長度、超時重傳、擁塞控制等方式實(shí)現(xiàn)了可靠傳輸。
連接管理:TCP 使用三次握手和四次揮手來保證可靠地建立連接和釋放連接。
校驗(yàn)和:用來檢查整個 TCP 報(bào)文段在傳輸過程中是否出現(xiàn)了誤碼。
序列號/確認(rèn)應(yīng)答:TCP 會給發(fā)送的每一個包進(jìn)行編號,接收方會對收到的包進(jìn)行應(yīng)答,發(fā)送方就會知道接收方是否收到對應(yīng)的包,如果發(fā)現(xiàn)沒有收到,就會重發(fā),這樣就能保證數(shù)據(jù)的完整性了。
流量控制:TCP 連接的每一方都有固定大小的緩沖空間,TCP 的接收端只允許發(fā)送端發(fā)送接收端緩沖區(qū)能接納的數(shù)據(jù)大小。當(dāng)接收方來不及處理發(fā)送方的數(shù)據(jù)時,能提示發(fā)送方降低發(fā)送的速率,防止包丟失。TCP 使用的流量控制協(xié)議是可變大小的滑動窗口協(xié)議。(TCP 利用滑動窗口實(shí)現(xiàn)流量控制)
最大消息長度:在建立 TCP 連接的時候,雙方約定一個最大的長度(MSS)作為發(fā)送的單位,重傳的時候也是以這個單位來進(jìn)行重傳的。理想情況下是該長度的數(shù)據(jù)剛好不被網(wǎng)絡(luò)層分塊。
超時重傳:超時重傳是指發(fā)送出去的數(shù)據(jù)包到接收到確認(rèn)包之間的時間,如果超過了這個時間,就會被認(rèn)為是丟包了,需要重傳。
擁塞控制:如果網(wǎng)絡(luò)非常擁堵,此時再發(fā)送數(shù)據(jù)就會加重網(wǎng)絡(luò)負(fù)擔(dān),那么發(fā)送的數(shù)據(jù)段很可能超過了最大生存時間也沒有到達(dá)接收方,就會產(chǎn)生丟包問題。為此 TCP 引入了慢啟動機(jī)制,先發(fā)出少量數(shù)據(jù),就像探路一樣,先摸清當(dāng)前的網(wǎng)絡(luò)擁堵狀態(tài)后,再決定按照多大的速度傳送數(shù)據(jù)。
29.說說 TCP 的流量控制?
TCP 提供了一種機(jī)制,可以讓發(fā)送方根據(jù)接收方的實(shí)際接收能力控制發(fā)送的數(shù)據(jù)量,這就是流量控制。
TCP 通過「滑動窗口」來實(shí)現(xiàn)流量控制
首先 TCP 雙方進(jìn)行三次握手,初始化各自的窗口大小,均為 400 字節(jié)。
假如當(dāng)前發(fā)送方給接收方發(fā)送了 200 字節(jié),那么,發(fā)送方的SND.NXT會右移 200 字節(jié),也就是說當(dāng)前的可用窗口減少了 200 字節(jié)。
接收方收到后,放到緩沖隊(duì)列里面,REV.WND = 400-200=200 字節(jié),所以 win=200 字節(jié)返回給發(fā)送方。接收方會在 ACK 的報(bào)文首部帶上縮小后的滑動窗口 200 字節(jié)
發(fā)送方又發(fā)送 200 字節(jié)過來,200 字節(jié)到達(dá),繼續(xù)放到緩沖隊(duì)列里面。不過這時候,由于大量負(fù)載的原因,接收方處理不了這么多字節(jié),只能處理 100 字節(jié),剩余的 100 字節(jié)繼續(xù)放到緩沖隊(duì)列里面。這時候,REV.WND = 400-200-100=100 字節(jié),即 win=100 字節(jié)返回給發(fā)送方。
發(fā)送方繼續(xù)發(fā)送 100 字節(jié)過來,這時候,接收窗口 win 變?yōu)?0。
發(fā)送方停止發(fā)送,開啟一個定時任務(wù),每隔一段時間,就去詢問接收方,直到 win 大于 0,才開始繼續(xù)發(fā)送。
30.詳細(xì)說說 TCP 的滑動窗口?
TCP 發(fā)送一個數(shù)據(jù),如果需要收到確認(rèn)應(yīng)答才會發(fā)送下一個數(shù)據(jù)。這樣的話就會有個缺點(diǎn):效率會比較低。
為了解決這個問題,TCP 引入了滑動窗口,它是操作系統(tǒng)開辟的一個緩存空間。窗口大小表示無需等待確認(rèn)應(yīng)答而可以繼續(xù)發(fā)送數(shù)據(jù)的最大值。
TCP 頭部有個 16 位的窗口大小,它告訴對方本端的 TCP 接收緩沖區(qū)還能容納多少字節(jié)的數(shù)據(jù),這樣對方就可以控制發(fā)送數(shù)據(jù)的速度,從而達(dá)到流量控制的目的。
通俗點(diǎn)講,就是接收方每次收到數(shù)據(jù)包,在發(fā)送確認(rèn)報(bào)文的時候,同時告訴發(fā)送方,自己的接收緩沖區(qū)還有多少空閑空間,緩沖區(qū)的空閑空間,我們就稱之為接收窗口大小。
TCP 滑動窗口分為兩種: 發(fā)送窗口和接收窗口。
發(fā)送方的滑動窗口包含四個部分:
- 已發(fā)送且已收到 ACK 確認(rèn)
- 已發(fā)送但未收到 ACK 確認(rèn)
- 未發(fā)送但可以發(fā)送
- 未發(fā)送且不可發(fā)送
- 虛線矩形框,就是發(fā)送窗口。
- SND.WND:表示發(fā)送窗口的大小,上圖虛線框的格子數(shù)是 14 個,即發(fā)送窗口大小是 14。
- SND.NXT:下一個發(fā)送的位置,它指向未發(fā)送但可以發(fā)送的第一個字節(jié)的序列號。
- SND.UNA:一個絕對指針,它指向的是已發(fā)送但未收到確認(rèn)的第一個字節(jié)的序列號。
接收方的滑動窗口包含三個部分:
- 已成功接收并確認(rèn)
- 未收到數(shù)據(jù)但可以接收
- 未收到數(shù)據(jù)且不可以接收的數(shù)據(jù)
- 虛線矩形框,就是接收窗口。
- REV.WND:表示接收窗口的大小,上圖虛線框的格子數(shù)就是 9 個,即接收窗口的大小是 9。
- REV.NXT:下一個接收的位置,它指向未收到但可以接收的第一個字節(jié)的序列號。
31.說說 TCP 的擁塞控制?
什么是擁塞控制?不是有了流量控制嗎?
前?的流量控制是避免發(fā)送?的數(shù)據(jù)填滿接收?的緩存,但是并不知道整個?絡(luò)中發(fā)?了什么。
?般來說,計(jì)算機(jī)?絡(luò)都處在?個共享的環(huán)境。因此也有可能會因?yàn)槠渌鳈C(jī)之間的通信使得?絡(luò)出現(xiàn)擁堵。
在?絡(luò)出現(xiàn)擁堵時,如果繼續(xù)發(fā)送?量數(shù)據(jù)包,可能會導(dǎo)致數(shù)據(jù)包延遲、丟失等,這時 TCP 就會重傳數(shù)據(jù),但是?重傳就會導(dǎo)致?絡(luò)的負(fù)擔(dān)更重,于是會導(dǎo)致更?的延遲以及更多的丟包,這個情況就會進(jìn)?惡性循環(huán)并且被不斷地放?…
所以,TCP 不能忽略整個網(wǎng)絡(luò)中發(fā)?的事,它被設(shè)計(jì)成?個?私的協(xié)議,當(dāng)?絡(luò)發(fā)送擁塞時,TCP 會?我犧牲,降低發(fā)送的數(shù)據(jù)流。
于是,就有了擁塞控制,擁塞控制的?的就是為了避免發(fā)送?的數(shù)據(jù)填滿整個?絡(luò)。
就像是一個水管,不能讓太多的水(數(shù)據(jù)流)流入水管,如果超過水管的承受能力,水管就會被撐爆(丟包)。
發(fā)送方維護(hù)一個擁塞窗口 cwnd(congestion window) 的變量,調(diào)節(jié)所要發(fā)送數(shù)據(jù)的量。
什么是擁塞窗??和發(fā)送窗?有什么關(guān)系呢?
擁塞窗? **cwnd **是發(fā)送?維護(hù)的?個狀態(tài)變量,它會根據(jù)?絡(luò)的擁塞程度動態(tài)變化。
發(fā)送窗? swnd 和接收窗? rwnd 是約等于的關(guān)系,那么由于加?了擁塞窗?的概念后,此時發(fā)送窗?的值 swnd = min(cwnd, rwnd),也就是取擁塞窗?和接收窗?中的最?值。
擁塞窗? cwnd 變化的規(guī)則:
- 只要?絡(luò)中沒有出現(xiàn)擁塞, cwnd 就會增?
- 但如果?絡(luò)中出現(xiàn)了擁塞, cwnd 就會減小
擁塞控制有哪些常用算法?
慢啟動
慢啟動算法,慢慢啟動。
它表示 TCP 建立連接完成后,一開始不要發(fā)送大量的數(shù)據(jù),而是先探測一下網(wǎng)絡(luò)的擁塞程度。由小到大逐漸增加擁塞窗口的大小,如果沒有出現(xiàn)丟包,每收到一個 ACK,就將擁塞窗口 cwnd 的大小加 1(單位是 MSS)。每輪次發(fā)送窗口增加一倍,呈指數(shù)增長,如果出現(xiàn)丟包,擁塞窗口就減半,進(jìn)入擁塞避免階段。
舉個例子:
- 連接建?完成后,?開始初始化 cwnd = 1 ,表示可以傳?個 MSS ??的數(shù)據(jù)。
- 當(dāng)收到?個 ACK 確認(rèn)應(yīng)答后,cwnd 增加 1,于是?次性能夠發(fā)送 2 個。
- 當(dāng)收到 2 個 ACK 確認(rèn)應(yīng)答后, cwnd 增加 2,于是就能?之前多發(fā)送 2 個,所以這?次能夠發(fā)送 4 個。
- 當(dāng)這 4 個 ACK 確認(rèn)到來的時候,每個確認(rèn) cwnd 增加 1, 4 個確認(rèn) cwnd 增加 4,于是就能?之前多發(fā)送 4 個,所以這?次能夠發(fā)送 8 個。
發(fā)送包的個數(shù)是呈指數(shù)性增?的。
為了防止 cwnd 增長過大而引起網(wǎng)絡(luò)擁塞,還需設(shè)置一個慢啟動閥值 ssthresh(slow start threshold)的狀態(tài)變量。當(dāng) cwnd 到達(dá)該閥值后,就好像水管被關(guān)小了水龍頭一樣,減少了擁塞狀態(tài)。即當(dāng) cwnd > ssthresh 時,進(jìn)入擁塞避免算法。
擁塞避免
一般來說,慢啟動閥值 ssthresh 的大小是 65535 字節(jié),cwnd 到達(dá)慢啟動閥值后
- 每收到一個 ACK 時,cwnd = cwnd + 1/cwnd
- 當(dāng)每過一個 RTT 時,cwnd = cwnd + 1
顯然這是一個線性上升的算法,可以避免發(fā)送過快導(dǎo)致網(wǎng)絡(luò)出現(xiàn)擁塞問題。
接著上面慢啟動的例子,假定 ssthresh 為 8:
- 當(dāng) 8 個 ACK 確認(rèn)應(yīng)答到來時,每個確認(rèn)增加 1/8,8 個 ACK 確認(rèn)后 cwnd ?共增加 1,于是這?次能夠發(fā)送 9 個 MSS ??的數(shù)據(jù),變成了線性增?。
擁塞發(fā)生
當(dāng)網(wǎng)絡(luò)擁塞發(fā)生丟包時,會有兩種情況:
- RTO 超時重傳
- 快速重傳
如果是發(fā)生了RTO 超時重傳,就會使用「擁塞發(fā)生」算法
- 慢啟動閥值 sshthresh = cwnd/2
- cwnd 重置為 1
- 進(jìn)入新的慢啟動過程
這真的是辛辛苦苦幾十年,一朝回到解放前。其實(shí)還有更好的處理方式,就是「快速重傳」。當(dāng)發(fā)送方收到 3 個連續(xù)的重復(fù) ACK 時,就會快速地重傳,不必等待RTO超時再重傳。
發(fā)?「快速重傳」的擁塞發(fā)?算法:
- 擁塞窗口大小 cwnd = cwnd/2
- 慢啟動閥值 ssthresh = cwnd
- 進(jìn)入快速恢復(fù)算法
快速恢復(fù)
快速重傳和快速恢復(fù)算法一般是同時使用的。快速恢復(fù)算法認(rèn)為,還能收到 3 個重復(fù)的 ACK,說明網(wǎng)絡(luò)也沒有那么糟糕,所以沒必要像 RTO超時重傳 那樣強(qiáng)烈。
正如前面所說的,進(jìn)入快速恢復(fù)之前,cwnd 和 sshthresh 已被更新:
- cwnd = cwnd/2
- sshthresh = cwnd
然后,真正進(jìn)入「快速恢復(fù)」算法:
- cwnd = sshthresh + 3
- 重傳重復(fù)的那幾個 ACK(即丟失的那幾個數(shù)據(jù)包)
- 如果再收到重復(fù)的 ACK,那么 cwnd = cwnd +1
- 如果收到新數(shù)據(jù)的 ACK 后,cwnd = sshthresh。因?yàn)槭盏叫聰?shù)據(jù)的 ACK,表明恢復(fù)過程已經(jīng)結(jié)束,可以再次進(jìn)入「擁塞避免」算法了。
32.說說 TCP 的重傳機(jī)制?
重傳包括:超時重傳、快速重傳、帶選擇確認(rèn)的重傳(SACK)、重復(fù) SACK 四種。
超時重傳
超時重傳,是 TCP 協(xié)議保證數(shù)據(jù)可靠性的另一個重要機(jī)制,其原理是在發(fā)送某一個數(shù)據(jù)以后就開啟一個重傳計(jì)時器,在一定時間內(nèi)如果沒有收到發(fā)送的數(shù)據(jù)報(bào)的 ACK 報(bào)文,那么就重新發(fā)送數(shù)據(jù),直到收到 ACK 報(bào)文為止。
超時時間應(yīng)該設(shè)置為多少合適呢?
RTT 就是數(shù)據(jù)完全發(fā)送完,到收到確認(rèn)信號的時間,即數(shù)據(jù)包的一次往返時間。
超時重傳時間,就是 RTO(Retransmission Timeout)。那么,RTO 應(yīng)該設(shè)置多大呢?
- 如果 RTO 設(shè)置很大,等了很久都沒重發(fā),這樣肯定不行。
- 如果 RTO 設(shè)置很小,那很可能數(shù)據(jù)都沒有丟失,就開始重發(fā)了,這將會導(dǎo)致網(wǎng)絡(luò)阻塞,從而發(fā)生惡性循環(huán),導(dǎo)致更多的超時出現(xiàn)。
一般來說,RTO 略微大于 RTT,效果是最佳的。
超時重傳并不是十分完美的重傳方案,它有這些缺點(diǎn):
- 當(dāng)一個報(bào)文丟失時,會等待一定的超時周期,才重傳分組,增加了端到端的時延。
- 當(dāng)一個報(bào)文丟失時,在其等待超時的過程中,可能會出現(xiàn)這種情況:其后面的報(bào)文段已經(jīng)被接收方接收了但卻遲遲得不到確認(rèn),發(fā)送方會認(rèn)為其后面的報(bào)文段也丟失了,從而引起不必要的重傳,既浪費(fèi)資源也浪費(fèi)時間。
快速重傳
快速重傳可以用來解決超時重發(fā)的時間等待問題。
它不以時間驅(qū)動,而是以數(shù)據(jù)驅(qū)動。它是基于接收方的反饋信息來引發(fā)重傳的。
快速重傳的流程如下:
發(fā)送方發(fā)送了 1,2,3,4,5,6 份數(shù)據(jù):
- 第一份 Seq=1 先送到了,于是 ACK 回2;
- 第二份 Seq=2 也送到了,于是 ACK 回3;
- 第三份 Seq=3 由于網(wǎng)絡(luò)等某些原因,沒送到;
- 第四份 Seq=4 送到了,但是由于 Seq=3 沒收到。因此 ACK 還是回3;
- 后面的 Seq=5,6 也送到了,ACK 還是回復(fù)3,因?yàn)?Seq=3 沒有收到。
- 發(fā)送方連續(xù)收到三個重復(fù)冗余的 ACK=3 的確認(rèn)(其實(shí)是4個哈,但是因?yàn)榍懊娴囊粋€是正常的ACK,后面三個才是重復(fù)冗余的),于是知道哪個報(bào)文段在傳輸過程中丟失了;發(fā)送方就在重傳定時器過期之前,重傳該報(bào)文段。
- 最后,接收方收到了 Seq=3,此時因?yàn)?Seq=4,5,6 都收到了,于是它回 ACK=7。
快速重傳機(jī)制也有缺點(diǎn):發(fā)送方并不知道到底是哪個報(bào)文丟失了,到底該重傳多少個數(shù)據(jù)包?
是只重傳 Seq=3 ?還是重傳 Seq=3、Seq=4、Seq=5、Seq=6 呢?因?yàn)榘l(fā)送方并不清楚這三個連續(xù)的 ACK=3 是誰傳回來的。
帶選擇確認(rèn)的重傳(SACK)
為了解決應(yīng)該重傳多少個包的問題? TCP 提供了帶選擇確認(rèn)的重傳(即 SACK,Selective Acknowledgment)。
SACK 機(jī)制就是,在快速重傳的基礎(chǔ)上,接收方返回最近收到報(bào)文段的序列號范圍,這樣發(fā)送方就知道接收方哪些數(shù)據(jù)包是沒收到的。這樣就很清楚應(yīng)該重傳哪些數(shù)據(jù)包。
如上圖中,發(fā)送?收到了三次同樣的 ACK 確認(rèn)報(bào)?,于是就會觸發(fā)「快速重傳」機(jī)制,通過 SACK 信息發(fā)現(xiàn)只有 200~299 這段數(shù)據(jù)丟失,則重發(fā)時,就只選擇了這個 TCP 段進(jìn)?重發(fā)。
重復(fù) SACK(D-SACK)
D-SACK,英文是 Duplicate SACK,是在 SACK 的基礎(chǔ)上做了一些擴(kuò)展,主要用來告訴發(fā)送方,有哪些數(shù)據(jù)包,自己重復(fù)接受了。
D-SACK 的目的是幫助發(fā)送方判斷,是否發(fā)生了包失序、ACK 丟失、包重復(fù)或偽重傳。讓 TCP 可以更好的做網(wǎng)絡(luò)流控。
例如 ACK 丟包導(dǎo)致的數(shù)據(jù)包重復(fù):
- 接收?發(fā)給發(fā)送?的兩個 ACK 確認(rèn)應(yīng)答都丟失了,所以發(fā)送?超時后,重傳第?個數(shù)據(jù)包(3000 ~ 3499)
- 接收?發(fā)現(xiàn)數(shù)據(jù)是重復(fù)收到的,于是回了?個 SACK = 3000
3500,告訴「發(fā)送?」 30003500的數(shù)據(jù)早已被接收了,因?yàn)?ACK 都到 4000 了,意味著 4000 之前的所有數(shù)據(jù)都已經(jīng)收到了,所以這個 SACK 就代表著 D-SACK 。這樣發(fā)送?就知道了,數(shù)據(jù)并沒有丟,而是接收?的 ACK 確認(rèn)報(bào)?丟了。
33.說說 TCP 的粘包和拆包?
什么是 TCP 粘包和拆包?
TCP 是面向字節(jié)流,沒有界限的一串?dāng)?shù)據(jù)。TCP 底層并不了解上層業(yè)務(wù)數(shù)據(jù)的具體含義,它會根據(jù) TCP 緩沖區(qū)的實(shí)際情況進(jìn)行包的劃分,所以在業(yè)務(wù)上認(rèn)為,一個完整的包可能會被 TCP 拆分成多個包進(jìn)行發(fā)送,也有可能把多個小的包封裝成一個大的數(shù)據(jù)包進(jìn)行發(fā)送,這就是所謂的 TCP 粘包和拆包問題。
為什么會產(chǎn)生粘包和拆包呢?
- 要發(fā)送的數(shù)據(jù)小于 TCP 發(fā)送緩沖區(qū)的大小,TCP 將多次寫入緩沖區(qū)的數(shù)據(jù)一次性發(fā)送出去,將會發(fā)生粘包;
- 接收方的應(yīng)用層沒有及時讀取接收緩沖區(qū)的數(shù)據(jù),將會發(fā)生粘包;
- 要發(fā)送的數(shù)據(jù)大于 TCP 發(fā)送緩沖區(qū)剩余空間的大小,將會發(fā)生拆包;
- 待發(fā)送的數(shù)據(jù)大于 MSS(最大報(bào)文長度),TCP 在傳輸前將會進(jìn)行拆包。即 TCP報(bào)文長度 - TCP頭部長度 > MSS。
解決方案:
- 發(fā)送方給每個數(shù)據(jù)包添加包首部,首部中應(yīng)該至少包含數(shù)據(jù)包的長度,這樣接收方在收到數(shù)據(jù)后,通過讀取包首部的長度字段,便知道每一個數(shù)據(jù)包的實(shí)際長度了。
- 發(fā)送方將每個數(shù)據(jù)包封裝為固定長度(不夠的可以通過補(bǔ)0填充),這樣接收方每次從接收緩沖區(qū)中讀取固定長度的數(shù)據(jù),就自然而然的把每個數(shù)據(jù)包拆分開來。
- 可以在數(shù)據(jù)包之間設(shè)置邊界,如添加特殊符號,這樣接收方通過這個邊界就可以將不同的數(shù)據(jù)包拆分開來。
-
主機(jī)
+關(guān)注
關(guān)注
0文章
982瀏覽量
35008 -
TCP
+關(guān)注
關(guān)注
8文章
1347瀏覽量
78933 -
UDP
+關(guān)注
關(guān)注
0文章
322瀏覽量
33849 -
數(shù)據(jù)鏈路
+關(guān)注
關(guān)注
0文章
25瀏覽量
8926
發(fā)布評論請先 登錄
相關(guān)推薦
評論