TCP 三次握手
所謂三次握手(Three-way Handshake),是指建立一個TCP連線時,需要客戶端和伺服器總共傳送3個包,那麼為什麼在TCP建立連線時是三次握手,而不是兩次或四次? TCP名為傳輸控制協議,是一種可靠的傳輸層協議。(原則上任何資料傳輸都無法確保絕對可靠,三次握手只是確保可靠的基本需要)
舉個例子,平常和女朋友打電話的時候(雖然我現在沒有女朋友@_@)
- 第一次握手
客戶端傳送syn包(syn=x)的資料包到伺服器,並進入SYN_SEND狀態,等待伺服器確認; - 第二次握手
伺服器收到syn包,必須確認客戶的SYN(ack=x+1),同時自己也傳送一個SYN包(syn=y),即SYN+ACK包,此時伺服器進入SYN_RECV狀態; - 第三次握手
客戶端收到伺服器的SYN+ACK包,向伺服器傳送確認包ACK(ack=y+1),此包傳送完畢,客戶端和伺服器進入ESTABLISHED狀態,完成三次握手。
注:握手過程中傳送的包裡不包含資料,三次握手完畢後,客戶端與伺服器才正式開始傳送資料。理想狀態下,TCP連線一旦建立,在通訊雙方中的任何一方主動關閉連線之前,TCP連線都將被一直保持下去。
位碼即TCP標誌位:
- SYN(synchronous建立聯機)
- ACK(acknowledgement 確認)
- PSH(push傳送)
- FIN(finish結束)
- RST(reset重置)
- URG(urgent緊急)
- Sequence number(seq 順序號碼)
- Acknowledge number(ack 確認號碼)
TCP 四次揮手
TCP的連線的拆除需要傳送四個包,因此稱為四次揮手(four-way handshake)。客戶端或伺服器均可主動發起揮手動作,在socket程式設計中,任何一方執行close()操作即可產生揮手操作。
舉個例子,和女朋友分手的時候(分手是件痛苦的事情,所以雙方儘量多些包容,少些爭吵,不要輕易說分手,畢竟在一起不容易)
對應客戶端與伺服器之間的通訊-
第一次揮手 主動關閉方傳送一個FIN,用來關閉主動方到被動關閉方的資料傳送,也就是主動關閉方告訴被動關閉方:我已經不會再給你發資料了(當然,在fin包之前傳送出去的資料,如果沒有收到對應的ack確認報文,主動關閉方依然會重發這些資料),但是,此時主動關閉方還可以接受資料。
-
第二次揮手 被動關閉方收到FIN包後,傳送一個ACK給對方,確認序號為收到序號+1(與SYN相同,一個FIN佔用一個序號, SYN 和 FIN 都有seq序號)。
-
第三次揮手 被動關閉方傳送一個FIN,用來關閉被動關閉方到主動關閉方的資料傳送,也就是告訴主動關閉方,我的資料也傳送完了,不會再給你發資料了。
-
第四次揮手 主動關閉方收到FIN後,傳送一個ACK給被動關閉方,確認序號為收到序號+1,至此,完成四次揮手。
注:任何一方(客戶端或伺服器)都可以選擇主動關閉,在雙方還沒有完全確定關閉連線時,還有可能存在沒有傳送完的資料
狀態說明:
- CLOSED: 這個表示初始狀態。
- LISTEN(伺服器): 表示伺服器端的某個SOCKET處於監聽狀態,可以接受連線了。
- ESTABLISHED:表示連線已經建立了。
- SOCKET:請自行百度
為什麼建立連線協議是三次握手,而關閉連線卻是四次握手呢?
這是因為服務端的LISTEN狀態下的SOCKET當收到SYN報文的建連請求後,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在一個報文裡來傳送。
當關閉連線時,當收到對方的FIN報文通知時,它僅僅表示對方沒有資料傳送給你了;但未必你所有的資料都全部傳送給對方了,所以你可能未必會馬上會關閉SOCKET,也即你可能還需要傳送一些資料給對方之後,再傳送FIN報文給對方來表示你同意現在可以關閉連線了,所以它這裡的ACK報文和FIN報文多數情況下都是分開傳送的。