詳解TCP數據包中SYN,ACK欄位與數據發送的關聯
- 2019 年 10 月 8 日
- 筆記
在TCP協議中,為了確保數據能穩定發送,協議使用數據包中的syn,ack兩個欄位來監控數據是否正確發生和接收,本節我們看看這兩個欄位如何保證數據的平穩傳輸。
假設客戶端和伺服器通過三次握手建立了連接,然後雙方準備互相發生數據。假設握手時客戶端將自己的syn欄位設置為0,而伺服器將自己的syn欄位設置為240,於是當伺服器收到客戶端的SYN包後,在返回的ACK+SYN數據包中,它附帶的ack欄位就會設置為1,也就是說伺服器認為客戶端下次發送數據時,數據包包含的syn欄位應該設置為1。當客戶端收到伺服器的ACK+SYN數據包後,返回的ACK數據包中會將ACK欄位設置為241,也就是說客戶端認為伺服器下次發送的數據對應的SYN編號為241.
我們假設數據包最大發送位元組數為536位元組,因此任何一方想發送超過這個長度的數據時,TCP會將數據切分成多個不超過536位元組的小塊。假設客戶端先發起請求,數據包中的數據是140位元組,假設客戶端和伺服器的滑動窗口大小都是361,由於已經發送了140位元組的數據,窗口內還剩220位元組數據可以發送,於是不等伺服器回應,客戶端繼續將剩下的220位元組數據發送給伺服器,注意這時候客戶端會將數據包中的SYN欄位設置為141,如此表明當前數據要跟在上次發送的140位元組數據後面,如果包含220位元組的數據包比包含140位元組的數據包先抵達伺服器端,那麼伺服器就可以通過syn欄位得知哪個包的數據在前哪個包的數據在後面。
假設伺服器收到了客戶端發來的140位元組數據包,此時它發送TCP數據包給客戶端,其中包含80位元組的數據,此時它的syn欄位要設置成241,同時ack欄位要設置成141,也就是告訴客戶端140位元組成功收到,讓它發送跟著在140位元組後面的數據。此時客戶端收到伺服器回發的數據包,讀取syn欄位發現其值為141,這時客戶端就知道發出的140位元組數據伺服器已經收到,這時候它就能把自己的移動窗口向後挪動140位元組。如果此時客戶端沒有數據要發送,那麼它會回發一個ACK包裡面的ack欄位設置為321,這相當於告訴伺服器80位元組的數據收到,請繼續發送80位元組後面的數據。
接下來伺服器繼續向客戶端發送120位元組數據,此時數據包中syn欄位設置為321,當客戶端收到這個該數據包後,回復ACK包給伺服器並且將其中的ack欄位設置為321+120=441,告訴伺服器120位元組的數據成功接收,此時伺服器就可以後移窗口120位元組。接下來伺服器繼續發送160位元組數據,此時包頭的syn欄位設置為441,一旦客戶端收到數據包後,它會構造一個ACK包,將其中的ack欄位設置為441+160=601發回給伺服器,告訴它成功接收到數據,當伺服器接收到客戶端的ACK包後,自己的所有數據都發送完畢,於是連接關閉階段,整個數據發送過程可由下圖表示:
這個過程看起來蠻複雜,實際上TCP協議運行的過程比當前描述要複雜得多,因為它必須處理多種意外情況。上面描述的通訊過程是」一問一答「,事實上客戶端可能一下子像伺服器發送多個請求,伺服器可以一下子回復多個數據包,同時伺服器或客戶端發送的ACK包中可能還會包含數據等。
其次一個ACK包可以同時回復前面多個數據包。伺服器可以同時將120位元組和160位元組數據包發送給客戶端,客戶端只要用ack欄位為601的ACK包回復給伺服器端即可。同時根據雙方各自情況還會有」流控制「,也就是一方要求另一方減少或增加一次數據包的數據量從而減緩接收壓力或提升接收效率。此外數據包在發送過程中可能會丟失,這時就需要觸發重傳機制,同時TCP協議還需實時監測是否有網路擁堵,一旦這種情況出現TCP就得啟動相應的應對機制等。
TCP協議異常複雜,因為它為了保障數據穩定傳輸同時還得面對各種意外網路情況,對於其他重要的協議細節,我們會在後續課程中繼續介紹。