邢臺手機網(wǎng)站建設(shè)公司seo排名點擊軟件推薦
文章目錄
- 零. TCP和UDP的區(qū)別以及TCP詳解
- TCP是如何保證可靠性的
- TCP超時重傳的原理
- TCP最大連接數(shù)限制
- TCP流量控制和擁塞控制
- 流量控制
- 擁塞控制
- TCP粘包問題
- 一、三次握手和四次揮手
- 二、為什么要進行三次握手?兩次握手可以嗎?
- 三、為什么要進行四次揮手?三次可以嗎?
- 四、第二次握手傳回來了ACK,為什么還要傳回SYN?
- 五. CLOSE-WAIT和TIME-WAIT的狀態(tài)和意義
- 六. TIME-WAIT為什么是2MSL
- 七. 有很多TIME-WAIT狀態(tài)要如何解決
- 八. 有很多CLOSE-WAIT狀態(tài)要如何解決
零. TCP和UDP的區(qū)別以及TCP詳解
TCP是如何保證可靠性的
- 數(shù)據(jù)分塊:應(yīng)用數(shù)據(jù)被分割成 TCP 認(rèn)為最適合發(fā)送的數(shù)據(jù)塊。
- 序列號和確認(rèn)應(yīng)答:TCP 給發(fā)送的每一個包進行編號,在傳輸?shù)倪^程中,每次接收方收到數(shù)據(jù)后,都會對傳輸方進行確認(rèn)應(yīng)答,即發(fā)送 ACK 報文,這個 ACK 報文當(dāng)中帶有對應(yīng)的確認(rèn)序列號,告訴發(fā)送方成功接收了哪些數(shù)據(jù)以及下一次的數(shù)據(jù)從哪里開始發(fā)。除此之外,接收方可以根據(jù)序列號對數(shù)據(jù)包進行排序,把有序數(shù)據(jù)傳送給應(yīng)用層,并丟棄重復(fù)的數(shù)據(jù)。
- 校驗和: TCP 將保持它首部和數(shù)據(jù)部分的檢驗和。這是一個端到端的檢驗和,目的是檢測數(shù)據(jù)在傳輸過程中的任何變化。如果收到報文段的檢驗和有差錯,TCP 將丟棄這個報文段并且不確認(rèn)收到此報文段。
- 流量控制:TCP 連接的雙方都有一個固定大小的緩沖空間,發(fā)送方發(fā)送的數(shù)據(jù)量不能超過接收端緩沖區(qū)的大小。當(dāng)接收方來不及處理發(fā)送方的數(shù)據(jù),會提示發(fā)送方降低發(fā)送的速率,防止產(chǎn)生丟包。TCP 通過滑動窗口協(xié)議來支持流量控制機制。
- 擁塞控制:當(dāng)網(wǎng)絡(luò)某個節(jié)點發(fā)生擁塞時,減少數(shù)據(jù)的發(fā)送。
- ARQ協(xié)議:也是為了實現(xiàn)可靠傳輸?shù)?#xff0c;它的基本原理就是每發(fā)完一個分組就停止發(fā)送,等待對方確認(rèn)。在收到確認(rèn)后再發(fā)下一個分組。
- 超時重傳:當(dāng) TCP 發(fā)出一個報文段后,它啟動一個定時器,等待目的端確認(rèn)收到這個報文段。如果超過某個時間還沒有收到確認(rèn),將重發(fā)這個報文段。
TCP超時重傳的原理
發(fā)送方在發(fā)送一次數(shù)據(jù)后就開啟一個定時器,在一定時間內(nèi)如果沒有得到發(fā)送數(shù)據(jù)報的ACK報文,那么就重新發(fā)送數(shù)據(jù),在達到一定次數(shù)還沒有成功的話就放棄重傳并發(fā)送一個復(fù)位信號。其中超時時間的計算是超時的核心,而定時時間的確定往往需要進行適當(dāng)?shù)臋?quán)衡,因為當(dāng)定時時間過長會造成網(wǎng)絡(luò)利用率不高,定時時間過短會造成多次重傳,使得網(wǎng)絡(luò)阻塞。在TCP連接的過程中,會參考當(dāng)前的網(wǎng)絡(luò)狀況從而找到一個合適的超時時間。
TCP最大連接數(shù)限制
-
Client 最大 TCP 連接數(shù)
client 在每次發(fā)起 TCP 連接請求時,如果自己并不指定端口的話,系統(tǒng)會隨機選擇一個本地端口(local port),該端口是獨占的,不能和其他 TCP 連接共享。TCP 端口的數(shù)據(jù)類型是 unsigned short,因此本地端口個數(shù)最大只有 65536,除了端口 0不能使用外,其他端口在空閑時都可以正常使用,這樣可用端口最多有 65535 個。 -
Server最大 TCP 連接數(shù)
server 通常固定在某個本地端口上監(jiān)聽,等待 client 的連接請求。不考慮地址重用(Unix 的 SO_REUSEADDR 選項)的情況下,即使 server 端有多個 IP,本地監(jiān)聽端口也是獨占的,因此 server 端 TCP 連接 4 元組中只有客戶端的 IP 地址和端口號是可變的,因此最大 TCP 連接為客戶端 IP 數(shù) × 客戶端 port 數(shù),對 IPV4,在不考慮 IP 地址分類的情況下,最大 TCP 連接數(shù)約為 2 的 32 次方(IP 數(shù))× 2 的 16 次方(port 數(shù)),也就是 server 端單機最大 TCP 連接數(shù)約為 2 的 48 次方。
TCP流量控制和擁塞控制
流量控制
流量控制就是讓發(fā)送方的發(fā)送速率不要太快,讓接收方來得及接收。如果接收方來不及接收發(fā)送方發(fā)送的數(shù)據(jù),那么就會有分組丟失。在TCP中利用可變長的滑動窗口機制可以很方便低在TCP連接上實現(xiàn)對發(fā)送方的流量控制。 實現(xiàn)方式是接收端返回的ACK中會包含自己的接收端的滑動窗口大小,以控制發(fā)送方此次發(fā)送的數(shù)據(jù)量大小。
如果接收方的滑動窗口滿了,基于TCP流量控制的滑動窗口協(xié)議,接收方返回給發(fā)送方的接收窗口大小為 0,此時發(fā)送方會等待接收方發(fā)送的窗口大小直到變?yōu)榉?0 為止,然而,接收方回應(yīng)的 ACK 包是存在丟失的可能的,為了防止雙方一直等待而出現(xiàn)死鎖情況,此時就需要堅持計時器來輔助發(fā)送方周期性地向接收方查詢,以便發(fā)現(xiàn)窗口是否變大。
擁塞控制
擁塞控制是作用于網(wǎng)絡(luò)的,它是防止過多的數(shù)據(jù)注入到網(wǎng)絡(luò)中,避免出現(xiàn)網(wǎng)絡(luò)負(fù)載過大的情況。常用的解決方法有:慢開始和擁塞避免、快重傳和快恢復(fù)。
- 慢開始
當(dāng)發(fā)送方開始發(fā)送數(shù)據(jù)時,由于一開始不知道網(wǎng)絡(luò)負(fù)荷情況,如果立即將大量的數(shù)據(jù)字節(jié)傳輸?shù)骄W(wǎng)絡(luò)中,那么就有可能引起網(wǎng)絡(luò)擁塞。一個較好的方法是在一開始發(fā)送少量的數(shù)據(jù)先探測一下網(wǎng)絡(luò)狀況,即由小到大的增大發(fā)送窗口(擁塞窗口 cwnd)。慢開始的慢指的是初始時令 cwnd為 1,即一開始發(fā)送一個報文段。如果收到確認(rèn),則 cwnd = 2,之后每收到一個確認(rèn)報文,就令 cwnd = cwnd* 2。
但是,為了防止擁塞窗口增長過大而引起網(wǎng)絡(luò)擁塞,另外設(shè)置了一個慢開始門限 ssthresh。
① 當(dāng) cwnd < ssthresh 時,使用上述的慢開始算法;
② 當(dāng) cwnd > ssthresh 時,停止使用慢開始,轉(zhuǎn)而使用擁塞避免算法;
③ 當(dāng) cwnd == ssthresh 時,兩者均可。
- 擁塞避免
擁塞控制是為了讓擁塞窗口 cwnd 緩慢地增大,即每經(jīng)過一個往返時間 RTT (往返時間定義為發(fā)送方發(fā)送數(shù)據(jù)到收到確認(rèn)報文所經(jīng)歷的時間)就把發(fā)送方的 cwnd 值加 1,通過讓 cwnd 線性增長,防止很快就遇到網(wǎng)絡(luò)擁塞狀態(tài)。
當(dāng)網(wǎng)絡(luò)擁塞發(fā)生時,讓新的慢開始門限值變?yōu)榘l(fā)生擁塞時候的值的一半,并將擁塞窗口置為 1 ,然后再次重復(fù)兩種算法(慢開始和擁塞避免),這時一瞬間會將網(wǎng)絡(luò)中的數(shù)據(jù)量大量降低。
-
快重傳
快重傳算法要求接收方每收到一個失序的報文就立即發(fā)送重復(fù)確認(rèn),而不要等到自己發(fā)送數(shù)據(jù)時才捎帶進行確認(rèn),假定發(fā)送方發(fā)送了 Msg 1 ~ Msg 4 這 4 個報文,已知接收方收到了 Msg 1,Msg 3 和 Msg 4 報文,此時因為接收到收到了失序的數(shù)據(jù)包,按照快重傳的約定,接收方應(yīng)立即向發(fā)送方發(fā)送 Msg 1 的重復(fù)確認(rèn)。 于是在接收方收到 Msg 4 報文的時候,向發(fā)送方發(fā)送的仍然是 Msg 1 的重復(fù)確認(rèn)。這樣,發(fā)送方就收到了 3 次 Msg 1 的重復(fù)確認(rèn),于是立即重傳對方未收到的 Msg 報文。由于發(fā)送方盡早重傳未被確認(rèn)的報文段,因此,快重傳算法可以提高網(wǎng)絡(luò)的吞吐量。 -
快恢復(fù)
快恢復(fù)算法是和快重傳算法配合使用的,該算法主要有以下兩個要點:
① 當(dāng)發(fā)送方連續(xù)收到三個重復(fù)確認(rèn),執(zhí)行乘法減小,慢開始門限 ssthresh 值減半;
② 由于發(fā)送方可能認(rèn)為網(wǎng)絡(luò)現(xiàn)在沒有擁塞,因此與慢開始不同,把 cwnd 值設(shè)置為 ssthresh 減半之后的值,然后執(zhí)行擁塞避免算法,線性增大 cwnd。
TCP粘包問題
為什么會出現(xiàn)TCP粘包和拆包?
- 當(dāng)發(fā)送方寫入的數(shù)據(jù)大于socket的緩沖區(qū)的大小的時候需要拆包?;蛘弋?dāng)TCP報文的數(shù)據(jù)部門大小大于MSS(最大報文長度)的時候?qū)霈F(xiàn)拆包。
- 當(dāng)發(fā)送方發(fā)送的數(shù)據(jù)太快,接收方處理數(shù)據(jù)的速度趕不上發(fā)送端的速度的時候?qū)l(fā)生粘包。
解決方案:
- 在消息的頭部添加消息長度字段,服務(wù)端獲取消息頭的時候解析消息長度,然后向后讀取相應(yīng)長度的內(nèi)容。
- 設(shè)置消息邊界,也可以理解為分隔符,服務(wù)端從數(shù)據(jù)流中按消息邊界分離出消息內(nèi)容,一般使用換行符。
一、三次握手和四次揮手
二、為什么要進行三次握手?兩次握手可以嗎?
第一次握手:客戶端只是發(fā)送處請求報文段,什么都無法確認(rèn),而服務(wù)器可以確認(rèn)自己的接收能力和對方的發(fā)送能力正常;
第二次握手:客戶端可以確認(rèn)自己發(fā)送能力和接收能力正常,對方發(fā)送能力和接收能力正常;
第三次握手:服務(wù)器可以確認(rèn)自己發(fā)送能力和接收能力正常,對方發(fā)送能力和接收能力正常;
可見三次握手才能讓雙方都確認(rèn)自己和對方的發(fā)送和接收能力全部正常,這樣就可以愉快地進行通信了。
一方面,如果只有第二次握手,服務(wù)端發(fā)給客服端的包丟了之后,服務(wù)端就直接建立了連接,然后一直傻等,從而造成服務(wù)器系統(tǒng)調(diào)用超時返回。
另一個方面,TCP 實現(xiàn)了可靠的數(shù)據(jù)傳輸,原因之一就是 TCP 報文段中維護了序號字段和確認(rèn)序號字段,通過這兩個字段雙方都可以知道在自己發(fā)出的數(shù)據(jù)中,哪些是已經(jīng)被對方確認(rèn)接收的。這兩個字段的值會在初始序號值得基礎(chǔ)遞增,如果是兩次握手,只有發(fā)送方(比如客戶端)的初始序號可以得到確認(rèn),而另一方的初始序號則得不到確認(rèn)。
三、為什么要進行四次揮手?三次可以嗎?
四次揮手可以被抽象為如下過程:
- Client: 請求關(guān)閉
- Server: 同意該請求
- Server: 請求關(guān)閉
- Client: 同意該請求
考慮以下服務(wù)器遭遇的場景,
先同意對方關(guān)閉連接,對方無法傳輸數(shù)據(jù);(第二次揮手)
自己若還有數(shù)據(jù)未發(fā)送完,接著發(fā)送直至全部發(fā)送完畢;
請求自身關(guān)閉連接;(第三次揮手)
客戶端同意(第四次揮手)
如果說服務(wù)器在客戶端請求關(guān)閉連接的一瞬間已經(jīng)沒有任何數(shù)據(jù)需要發(fā)送了,那么三次揮手應(yīng)該也是可以的,但是在實際生產(chǎn)環(huán)境中這樣的情況幾乎沒有,所以需要服務(wù)器先把自己的所有數(shù)據(jù)發(fā)送完畢,因此四次揮手更加穩(wěn)妥。
或者也可以這么回答:
釋放 TCP 連接時之所以需要四次揮手,是因為 FIN 釋放連接報文和 ACK 確認(rèn)接收報文是分別在兩次握手中傳輸?shù)摹?當(dāng)主動方在數(shù)據(jù)傳送結(jié)束后發(fā)出連接釋放的通知,由于被動方可能還有必要的數(shù)據(jù)要處理,所以會先返回 ACK 確認(rèn)收到報文。當(dāng)被動方也沒有數(shù)據(jù)再發(fā)送的時候,則發(fā)出連接釋放通知,對方確認(rèn)后才完全關(guān)閉TCP連接。
四、第二次握手傳回來了ACK,為什么還要傳回SYN?
ACK是為了告訴客戶端發(fā)來的數(shù)據(jù)接收無誤,傳回SYN是為了把自己的初始序列號同步到客戶端。
五. CLOSE-WAIT和TIME-WAIT的狀態(tài)和意義
CLOSE- WAIT發(fā)生在第二次揮手請求發(fā)送之后。
在服務(wù)器收到了客戶端關(guān)閉連接的請求并且告訴客戶端自己已經(jīng)成功收到了該請求之后,服務(wù)器進入了CLOSE- WAIT狀態(tài),然而此時有可能服務(wù)端還有一些數(shù)據(jù)還沒有傳輸完成,CLOSE- WAIT狀態(tài)就是用來保證服務(wù)器在關(guān)閉連接之前能夠?qū)⒋l(fā)送的所有數(shù)據(jù)發(fā)送完成,因此不能立即關(guān)閉連接。
TIME-WAIT發(fā)生在第四次揮手的時候,當(dāng)客戶端向服務(wù)端發(fā)送ACK確認(rèn)報文后進入該狀態(tài)。作用有兩個
- 客戶端立即關(guān)閉后,立即又用同樣的端口握手并建立通信,此時上次的連接殘留的數(shù)據(jù)包會被誤認(rèn)為是最新連接的,造成數(shù)據(jù)異常,
- 客戶端直接關(guān)閉后,若服務(wù)端重新發(fā)送 fin 包,客戶端就會回應(yīng) RST,會報異常,但是其實是沒有問題的
六. TIME-WAIT為什么是2MSL
當(dāng)客戶端發(fā)出最后的ACK確認(rèn)報文時,并不能確定服務(wù)器能夠接收到該段報文。所以客戶端在發(fā)送完ACK確認(rèn)報文之后,會設(shè)置一個時長為2MSL的計時器。
如果服務(wù)器在1MSL后仍然沒有收到客戶端發(fā)送的ACK確認(rèn)報文,那么它會向客戶端重傳FIN報文,對客戶端而言,從客戶端發(fā)出ACK報文起,重傳的FIN報文的最晚到達時間是2MSL。
若服務(wù)器在1MSL內(nèi)沒有收到客戶端發(fā)出的ACK確認(rèn)報文,再次向客戶端發(fā)送FIN釋放連接報文。若客戶端在2MSL內(nèi)收到了服務(wù)器在此發(fā)來的FIN報文,客戶端將再次向服務(wù)器發(fā)出ACK確認(rèn)報文,并重新開始2MSL的計時。
七. 有很多TIME-WAIT狀態(tài)要如何解決
服務(wù)器可以設(shè)置 SO_REUSEADDR 套接字選項來通知內(nèi)核,如果端口被占用,但 TCP 連接位于 TIME_WAIT 狀態(tài)時可以重用端口。如果你的服務(wù)器程序停止后想立即重啟,而新的套接字依舊希望使用同一端口,此時 SO_REUSEADDR 選項就可以避免 TIME-WAIT 狀態(tài)。
實際上,要建立長連接的話,就需要使用SO_REUSEADDR關(guān)鍵字。
八. 有很多CLOSE-WAIT狀態(tài)要如何解決
一般來說,系統(tǒng)內(nèi)不會出現(xiàn)很多CLOSE- WAIT(第二次揮手后服務(wù)器出現(xiàn)的狀態(tài))。我們可以首先檢查一下是不是自己的代碼出現(xiàn)了問題,比如查看服務(wù)端是否忘記關(guān)閉連接。其次我們可以調(diào)整系統(tǒng)參數(shù),包括句柄相關(guān)參數(shù)和TCP/IP的參數(shù),一般一個CLOSE_WAIT會維持至少兩個小時。