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