【Linux網路】TCP和UDP

一、TCP連接和斷開連接的過程
1.連接過程:

  • (1)第一次握手:客戶端向服務器端發送請求連接報文SYN,然後進入SYN_SENT狀態,即已發送狀態。
  • (2)第二次握手:服務器端收到客戶端發的SYN報文後,發送ACK進行確認,併發送自己的請求連接報文SYN報文,此時服務器端進入SYN_RECV狀態,即已接受狀態。
  • (3)第三次握手:客戶端收到服務器端的ACK和SYN後,此時客戶端進入EStablished狀態,即已完成連接狀態。然後客戶端發送ACK對服務器端的SYN進行最後確認,服務器端收到ACK確認之後也進入EStablished狀態,也就是已完成連接狀態。在此之後,服務器端和客戶端已完成建立連接的過程。

2.斷開過程:

  • (1)第一次揮手:客戶端向服務器端發送請求斷開連接的FIN報文,此時客戶端進入FIN_WAIT1狀態,就是關閉發數據通道,但是還可以接收數據。
  • (2)第二次揮手:服務器端收到客戶端的請求關閉連接的FIN報文後,然後發送ACK進行確認。此時服務器進入CLOSE_WAIT狀態,即等待關閉狀態。這個可以理解爲等待關閉發數據通道的狀態。此時,客戶端進入FIN_WAIT2狀態,等待服務器端發送關閉發數據的請求。
  • (3)第三次揮手:服務器端發送自己的請求斷開連接的FIN報文,此時服務器進入進入LAST_ACK狀態,即等待最後ACK確認
  • (4)第四次揮手:客戶端收到服務器發送的請求斷開連接的FIN報文後,然後發送ACK對其進行確認。此時客戶端進入到TIME_WAIT狀態。

二、TCP連接和斷開過程中常見的問題
1.連接過程倆次握手可以嗎?四次握手可以嗎?

答:首先倆次是不可以的,原因如下:若客戶端發送出的第一個SYN請求連接的報文段並沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以後的某個時間纔到達服務器。本來這是一個早已失效的報文段。但服務器收到此失效的SYN報文後,就會誤認爲是客戶端發出的一個新的連接請求。於是就向客戶端發出確認報文段,同意建立連接。假設不採用“三次握手”,那麼只要服務器發出確認,新的連接就建立了。由於現在客戶端並沒有發出建立連接的請求,因此不會對服務器發出的SYN報文進行確認,也不會向服務器發送數據。但服務器認爲新的連接已經建立,並一直等待客戶端發來數據。這樣,服務器的很多資源就白白浪費掉了。採用“三次握手”的方法可以防止上述現象發生。例如剛纔那種情況,客戶端不會向服務器的確認發出確認。server由於收不到確認,就知道客戶端並沒有要求建立連接。主要目的防止服務器一直等待,浪費資源。
四次握手也是可以的,但是效率相對於三次握手比較低,即服務將自己的ACK和SYN分開發送。

2.斷開過程三次揮手可以嗎?

答:可以的!被動方反饋的ACK和發送的FIN合併。

3.如果建立了連接,但是客戶端突然故障了怎麼辦?

答:TCP還設有一個保活計時器,顯然,客戶端如果出現故障,服務器不能一直等下去,白白浪費資源。服務器每收到一次客戶端的請求後都會重新復位這個計時器,時間通常是設置爲2小時,若兩小時還沒有收到客戶端的任何數據,服務器就會發送一個探測報文段,以後每隔75秒鐘發送一次。若一連發送10個探測報文仍然沒反應,服務器就認爲客戶端出了故障,接着就關閉連接。

4.TIME_WAIT的作用?

答:作用主要有以下倆種作用。

  • (1)保證遲來的報文段能被識別並丟棄。
  • (2)保證TCP斷開過程的可靠性。保證對端能收到最後的一個ACK,如果ACK丟失,在TIME_WAIT狀態本端還可以接受到對端重傳的FIN報文段並重新發送ACK。TIME_WAIT的存在時間爲2MSL

三、TCP和UDP的頭部信息

1.TCP報頭信息:

頭部長度字段:佔4比特。給出頭部佔32比特的數目。由於TCP報頭的長度隨TCP選項字段內容的不同而變化,因此報頭中包含一個指定報頭字段的字段。該字段以32比特爲單位,所以報頭長度一定是32比特的整數倍,有時需要在報頭末尾補0。如果報頭沒有TCP選項字段,則報頭長度值爲5,表示報頭一個有160比特,即20字節。
標誌位字段(U、A、P、R、S、F):佔6 bits,各比特的含義如下:
URG:報文段緊急。
ACK:確認序號有效。
PSH:接收方應該儘快將這個報文段交給應用層。
RST:重建連接。
SYN:發起一個連接。在握手完成後SYN爲1,表示TCP建立已連接。此後的所有報文段中,SYN都被置0
FIN:釋放一個連接。如果源主機數據發送完畢,將把該連接下要發送的最後一個報文段的報頭中的FIN位置1,或將該報文段後面發送的報頭中該位置1。
窗口大小字段:佔16比特。此字段用來進行流量控制。單位爲字節數,這個值是本機期望一次接收的字節數。接收計算機可接收的新數據字節的數量,根據接收緩衝區可用資源的大小,其值隨計算機所發送的每個報文段而變化。源主機可以利用接收到的窗口值決定下一個報文段的大小。
TCP校驗和字段:佔16比特。對整個TCP報文段,即TCP頭部和TCP數據進行校驗和計算,並由目標端進行驗證。
緊急指針字段:佔16比特。它是一個偏移量,和序號字段中的值相加表示緊急數據最後一個字節的序號。如果URG爲1,則緊急指針標誌着緊急數據的結束。其值是緊急數據最後1字節的序號,表示報文段序號的偏移量。例如,如果報文段的序號是1000,前8個字節都是緊急數據,那麼緊急指針就是8。緊急指針一般用途是使用戶可中止進程。
選項字段:佔32比特。可能包括"窗口擴大因子"、"時間戳"等選項。
數據部分:報頭後面是可選的報文段數據部分。求株距能接收最長達576字節的數據報。無其他選項的IP報頭是20字節,無其他選項的TCP報頭也是20字節,所以IP選項和TCP選項且含有多達536字節數據的TCP報文段無須分片就可達到目的主機。

2.UDP報頭信息:

源、目標端口號字段:佔16比特。作用與TCP數據段中的端口號字段相同,用來標識源端和目標端的應用進程。
長度字段:佔16比特。標明UDP頭部和UDP數據的總長度字節。
校驗和字段:佔16比特。用來對UDP頭部和UDP數據進行校驗。和TCP不同的是,對UDP來說,此字段是可選項,而TCP數據段中的校驗和字段是必須有的

四、TCP和UDP的區別

  • 1.TCP面向連接的,UDP是無連接的。
    建立連接:客戶機、服務器在交換消息之前都需要建立一個連接;在應用層傳輸數據之前,必須先建立TCP連接;客戶機/服務器進程間需要建立連接。
    無需連接建立:UDP不需要任何準備即可進行數據傳輸(TCP在開始數據傳輸之前要經過3次握手)。 
    無連接狀態:UDP不維護連接狀態(TCP需要在端系統中維護連接狀態)
  • 2.TCP提供可靠的流式服務,UDP提供不可靠的數據報服務。 可以通過頭部結構可以看出來(後面詳解)
  • 3.TCP對系統資源的要求比較多,UDP比較少。 可以從頭部信息得知,系統爲了TCP的傳輸維護了許多信息。
  • 4.UDP的程序結構比TCP要簡單。
  • 5.TCP保證數據正確性,UDP可能丟包;TCP保證數據順序,UDP不保證。

五、TCP可靠性保證

首先先來介紹幾個名詞:
——————————————————————————————————
ssthresh:慢開始啓動門限。
ssthresh作用:爲了防止擁塞窗口cwnd增長過大引起網絡擁塞,還需要設置一個慢開始門限ssthresh狀態變量。慢開始門限ssthresh的用法如下:
———當cwnd<ssthresh時,使用慢開始算法。
———當cwnd>ssthresh時,停止使用慢開始算法而改用擁塞避免算法。
———當cwnd=ssthresh時,既可使用慢開始算法,也可使用擁塞控制避免算法。
cwnd:擁塞窗口(CongestionWindow,CWND),每次發送的最大的MSS的個數。
swnd:擁塞控制的最終受控變量是發送端向網絡-次連續寫人(收到其中第一個數據的確認之前)的數據量,我們稱爲SWND(SendWindow,發送窗口9)。實際的SWND值是RWND和CWND中的較小者。不過,發送端最終以TCP報文段來發送數據,所以SWND限定了發送端能連續發送的TCP報文段數量。
MSS:(Maximum SegmentSize,最大報文段大小)是指TCP層所能夠接收的最大段大小,該值只包括TCP段的數據部分,不包括選項部分。
SMSS:這些TCP報文段的最大長度(僅指數據部分)稱爲SMSS(Sender Maximum SegmentSize,發送者最大段大小),其值一般等於MSS。

1.慢開始:

在剛剛開始發送報文段時,先把擁塞窗口cwnd設置爲1個最大報文段MSS的數值,而後每收到一個對新的報文段的確認,就把擁塞窗口增加1個MSS的數值,這樣擁塞窗口cwnd的值就隨着傳輸輪次(一個輪次即發送完一個cwnd的MSS)呈指數級增長,事實上,慢啓動的速度一點也不慢,只是它的起點比較低一點而已。用這樣的方法逐步增大發送方的擁塞窗口cwnd,可以使分組注入到網絡的速率更加合理。

2.擁塞避免算法:

當cwnd>=ssthresh時,就會進入“擁塞避免算法”,讓擁塞窗口cwnd緩慢地增大,每收到1個ACK擁塞窗口cwnd =(cwnd + 1) / cwnd,即每經過一個傳輸輪次就把發送方的擁塞窗口cwnd加1。這樣擁塞窗口cwnd按線性規律緩慢增長,比慢開始算法的擁塞窗口增長速率緩慢得多。擁塞避免算法是無法從根本上避免網絡擁堵,只能減少網絡擁堵。

注意事項:

無論在慢開始階段還是在擁塞避免階段,只要發送方判斷網絡出現擁塞(超時計時器RTO時限已到但還未收到確認),就要把慢開始門限ssthresh=cwnd/2,然後將擁塞窗口置爲1(cwnd=1),然後執行慢開始算法。這樣做的目的就是要迅速減少主機發送到網絡中的分組數,使得發生擁塞的路由器有足夠時間把隊列中積壓的分組處理完畢

  • (1)當TCP連接進行初始化時,把擁塞窗口cwnd置爲1MSS,慢開始門限的初始值設置爲16個MSS,即ssthresh = 16 。
  • (2)在執行慢開始算法時,擁塞窗口cwnd的初始值爲1。以後發送方每收到一個對新報文段的確認ACK,就把擁塞窗口cwnd乘二,則每個傳輸輪次擁塞窗口cwnd翻倍,因此在慢開始階段擁塞窗口cwnd隨着傳輸輪次按指數規律增長。
  • (3)當擁塞窗口cwnd增長到慢開始門限值ssthresh時(即當cwnd=16時),就改爲執行擁塞控制算法,每個傳輸輪次擁塞窗口cwnd加1,因此在擁塞控制階段擁塞窗口cwnd隨着傳輸輪次按線性規律增長。
  • (4)假定擁塞窗口的數值增長到24時,超時計時器RTO時限已到但還沒有收到確認,則認爲網絡出現超時(這很可能就是網絡發生擁塞了)。更新後的ssthresh值變爲ssthresh/2=12,擁塞窗口cwnd=1,然後繼續進入慢開始階段。

3.快重傳算法:

首先要求接收方每收到一個失序的報文段就立即發出重複確認(爲的是使發送方及早知道有報文段沒有到達對方),然後若是發送方接收到3個重複確認ACK,則啓動快重傳算法。

  • 接收方收到了M1和M2後都分別發出了確認。現在假定接收方沒有收到M3但接着收到了M4、M5、M6。顯然,接收方不能確認M4、M5、M6,因爲M4、M5、M6是收到的失序報文段。按照快重傳算法的規定,接收方應及時發送對M2的重複確認,這樣,發送方共收到了接收方的四個對M2的確認,其中後三個都是重複確認。快重傳算法還規定,發送方只要一連收到三個重複確認就應當立即重傳對方尚未收到的報文段M3,而不必繼續等待M3設置的重傳計時器RTO到期。

4.快速恢復算法:

TCP Reno算法定義在RFC5681。快速重傳和快速恢復算法一般同時使用。快速恢復算法認爲,你還有3個Duplicated Acks說明網絡也不那麼糟糕,所以沒有必要像RTO超時那麼強烈,並不需要重新回到慢啓動進行,這樣可能降低效率。

  • 所以協議棧會做如下工作:
    (1)擁塞窗口減半cwnd=cwnd/2
    (2)慢開始門限ssthresh=cwnd(減半後的值)
  • 然後啓動快速恢復算法:
    (3)設置cwnd = ssthresh+ack個數(一般是3個Dup Acks),然後重傳指定的數據包;
    (4)如果再次收到Dup Acks,則cwnd=cwnd+1,並且在條件允許的情況下發送下一個報文段(非重傳報文段)
    (5)如果收到新的ACK, 則快速恢復算法結束,設置cwnd = ssthresh,進入擁塞避免階段

快速重傳算法存在的問題

那就是——它依賴於3個重複的ACK。因爲3個重複的ACK並不代表只丟了一個數據包,很有可能是丟了好多包。但這個算法只會重傳一個,而剩下的那些包只能等到RTO超時,於是,進入了惡夢模式——超時一個阻塞窗口減半,多個超時會超成TCP的傳輸速度呈級數下降,而且也不會觸發快速恢復算法了。

快速重傳算法的改進

TCP New Reno算法:這個算法是Reno算法的改進,沒有使用SACK機制 當發送者這邊收到了3個Duplicated Acks,進入快速恢復模式,開始重傳重複acks指示的那個包。如果只有這一個包丟了,那麼,重傳這個包後回來的ack會把整個已經被髮送方傳輸出去的數據的ack返回來。如果沒有的話,說明有多個包丟了。我們稱此ACK爲Partial ACK。一旦發送方這邊發現了Partial ACK出現,那麼發送方就可以推理出來有多個包被丟了,於是繼續重傳滑動窗口裏未被ack的第一個包。直到再也收不到了Partial Ack,才真正結束快速恢復這個過程。

  • 接收方根據自己的接收能力設定了接收窗口rwnd,並把這個窗口值寫入TCP首部中的窗口字段,傳送給發送方。因此,接收窗口又稱爲通知窗口。
  • 因此,從接收方對發送方的流量控制的角度考慮, 發送方的發送窗口一定不能超過對方給出的接收窗口rwnd。發送方窗口的上限值 = min [ rwnd, cwnd ]
    • 當rwnd < cwnd時,是接收方的接收能力限制發送方窗口的最大值。
    • 當cwnd < rwnd時,則是網絡的擁塞限制發送方窗口的最大值。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章