文章目錄
轉自如下兩篇文章:
TCP的三次握手與四次揮手理解及面試題(很全面)
面試官,不要再問我三次握手和四次揮手
每次看了TCP的三次握手和四次揮手,總是過一段時間就忘記了,寫此文加深理解和記憶。
如下圖所示,TCP首部中有很多信息,在這裏我們需要關注的是 序號
,確認號
,ACK
, SYN
, FIN
等標誌位
。
ISN(Initial Sequence Number)
:初始序列號。ACK(確認字符,Acknowledge Character)
:佔1位,僅當ACK
=1時,確認號字段纔有效。ACK
=0時,確認號無效。SYN(同步序列編號,Synchronize Sequence Numbers)
:是TCP/IP建立連接時使用的握手信號。當SYN
=1,ACK
=0時表示:這是一個連接請求報文段。若同意連接,則在響應報文段中使得SYN
=1,ACK
=1。因此,SYN
=1表示這是一個連接請求,或連接接受報文。SYN
這個標誌位只有在TCP
建產連接時纔會被置1,握手完成後SYN
標誌位被置0。FIN
:用來釋放一個連接。FIN=1表示:此報文段的發送方的數據已經發送完畢,並要求釋放傳輸連接。- 序號
seq
:佔4個字節,用來標記數據段的順序,TCP
把連接中發送的所有數據字節都編上一個序號,第一個字節的編號(ISN
)由本地隨機產生;給字節編上序號後,就給每一個報文段指派一個序號;序列號seq就是這個報文段中的第一個字節的數據編號。有了序號才知道傳輸的數據的順序,在服務端才能正確組裝信息。 - 確認號
ack
:佔4個字節,期待收到對方下一個報文段的第一個數據字節的序號;確認號指的是期望接收到下一個字節的編號;因此當前報文段最後一個字節的編號+1即爲確認號。
PS:ACK、SYN和FIN這些大寫的單詞表示標誌位,其值要麼是1,要麼是0;ack、seq小寫的單詞表示序號。
下圖表表示了各標誌位的含義:
三次握手:
- 第一次握手:客戶端給服務端發一個
SYN
報文,並指明客戶端的初始化序列號ISN
。此時客戶端處於SYN_SENT
狀態。
首部的同步位SYN
=1,初始序號seq=x,SYN
=1的報文段不能攜帶數據,但要消耗掉一個序號。
- 第二次握手:服務器收到客戶端的
SYN
報文之後,會以自己的SYN
報文作爲應答,並且也指定了自己的初始化序列號ISN(s)
。同時會把客戶端的ISN
+ 1 作爲ACK
的值,表示自己已經收到了客戶端的 SYN,此時服務器處於SYN_RCVD
的狀態。這次握手實際做了兩件事,一是告訴客戶端收到了其SYN包,二是發送自己的SYN包來請求連接。
在確認報文段中SYN
=1,ACK
=1,確認號ack=x+1,初始序號seq=y。
- 第三次握手:客戶端收到
SYN
報文之後,會發送一個ACK
報文,當然,也是一樣把服務器的ISN
+ 1 作爲ACK
的值,表示已經收到了服務端的SYN
報文,此時客戶端處於ESTABLISHED
狀態。服務器收到ACK
報文之後,也處於ESTABLISHED
狀態,此時,雙方已建立起了連接。
確認報文段ACK
=1,確認號ack=y+1,序號seq=x+1(初始爲seq=x,第二個報文段所以要+1),ACK報文段可以攜帶數據,不攜帶數據則不消耗序號。
四次揮手:
- 第一次揮手:客戶端發送一個
FIN
報文,報文中會指定一個序列號。此時客戶端處於FIN_WAIT_1
狀態。
即發出連接釋放報文段(FIN
=1,序號seq=u),並停止再發送數據,主動關閉TCP
連接,進入FIN_WAIT_1(終止等待1)
狀態,等待服務端的確認。 - 第二次揮手:服務端收到
FIN
之後,會發送ACK
報文,且把客戶端的序列號值 +1 作爲ACK
報文的序列號值,表明已經收到客戶端的報文了,此時服務端處於CLOSE_WAIT
狀態。即服務端收到連接釋放報文段後即發出確認報文段(ACK
=1,確認號ack=u+1,序號seq=v),服務端進入CLOSE_WAIT(關閉等待)
狀態,此時的TCP
處於半關閉狀態,客戶端到服務端的連接釋放。客戶端收到服務端的確認後,進入FIN_WAIT_2(終止等待2)
狀態,等待服務端發出的連接釋放報文段。 - 第三次揮手:如果服務端也想斷開連接了,和客戶端的第一次揮手一樣,發給
FIN
報文,且指定一個序列號。此時服務端處於LAST_ACK
的狀態。即服務端沒有要向客戶端發出的數據,服務端發出連接釋放報文段(FIN
=1,ACK
=1,序號seq=w,確認號ack=u+1),服務端進入LAST_ACK(最後確認)
狀態,等待客戶端的確認。 - 第四次揮手:客戶端收到
FIN
之後,一樣發送一個ACK
報文作爲應答,且把服務端的序列號值 +1 作爲自己ACK
報文的序列號值,此時客戶端處於TIME_WAIT
狀態。需要過一陣子以確保服務端收到自己的ACK
報文之後纔會進入CLOSED
狀態,服務端收到ACK
報文之後,就處於關閉連接了,處於CLOSED
狀態。
即客戶端收到服務端的連接釋放報文段後,對此發出確認報文段(ACK
=1,seq=u+1,ack=w+1),客戶端進入TIME_WAIT(時間等待)
狀態。此時TCP
未釋放掉,需要經過時間等待計時器設置的時間2MSL
後,客戶端才進入CLOSED
狀態。
嘗試回答下面的問題來確認是否真的理解了。
- 爲什麼需要三次握手,兩次不行嗎?
- 什麼是半連接隊列?
- ISN(Initial Sequence Number)是固定的嗎?
- 三次握手過程中可以攜帶數據嗎?
- SYN攻擊是什麼?
- 爲什麼連接的時候是三次握手,關閉的時候卻是四次握手?
- 爲什麼TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?
- 如果已經建立了連接,但是客戶端突然出現故障了怎麼辦?
這些問題的答案見 :