一、三次握手:
TCP是面向連接配接的協定,通過保證建立的雙向連接配接,實作資料的安全穩定傳輸。三次握手是伺服器與用戶端建立連接配接時的過程。在伺服器使用accept()函數阻塞等待用戶端的連接配接,當有用戶端調用connect()函數時,開始進行三次握手建立連接配接,成功建立後,accept()函數解阻塞,執行後序的任務。
1、簡述這個過程:
- 用戶端向伺服器發送了一個資訊,目的告訴伺服器,用戶端想要建立連接配接
- 伺服器給用戶端回應一個資訊,有兩個目的,一是告訴用戶端,伺服器可以成功收到用戶端發送的資訊,二是确認用戶端可以收到伺服器發送的資訊
- 用戶端收到伺服器傳回的資訊後,再次給伺服器傳回一個資訊,目的是告訴伺服器,用戶端可以成功接收伺服器的資訊;
2、詳述這個過程:
- 第一次握手:用戶端向伺服器發送了一個請求連接配接封包,封包中重要的有兩個資料,一個是SYN=1,這是一個标志符,當SYN=1代表請求建立連接配接,另一個是seq=x,TCP傳輸的資料是位元組流的,seq是TCP位元組流中的一個編号,他也用來區分是哪一個伺服器/用戶端,所有學習時普遍使用x代表它的值;
- 第二次握手:伺服器接收到這個請求封包後,準備一個響應封包,封包重要資料主要有4個:ACK=1,ACK也是一個标志符,ACK=1代表确認接收到了來自對方的消息;seq=y,同為位元組流中的編号;SYN=1,TCP是建立雙向的連接配接,所有伺服器也發送一個請求連接配接的資訊;ack=x+1,ack是對用戶端發送的seq的回應,将用戶端發送的seq編号加1放在ack回應裡發送給用戶端;
- 第三次握手:用戶端收到伺服器傳回的響應和建立連接配接請求,目前确定了伺服器可以接收到用戶端的資訊,是以最後一次握手是确定用戶端可以收到伺服器的位址,這時用戶端向伺服器發送一個資料包,重要資料有:ACK=1表示可以接收資訊;ack=y+1,将伺服器的seq加1放到ack中;seq=x+1,表示自己是哪個用戶端。
3、為什麼是三次握手?
TCP要建立安全穩定的雙向連接配接,必須保證雙方都接接收到來自對方的資訊,第一次和第二次确定了伺服器可以接收到用戶端的資訊,第三次确定了用戶端可以接收伺服器的資訊,是以最少是三次。
4、圖解三次握手

二、四次揮手
1、簡述這個過程
- 用戶端向伺服器發送一個消息,告訴伺服器,用戶端準備斷開連接配接,并不會在發送資料資訊了
- 伺服器收到用戶端的請求,傳回一個資訊,告訴用戶端收到了這個資訊
- 伺服器向用戶端發送資訊,告訴用戶端,伺服器準備斷開連接配接
- 用戶端收到這個資訊後,告訴伺服器收到了這個資訊,此時雙方資訊确定,斷開連接配接
2、詳述這個過程
- 用戶端調用close()函數,向伺服器發送連接配接釋放封包,封包中有兩個重要的資料,FIN=1,标志符,FIN=1表示請求斷開連接配接,seq=u,用戶端資料位元組流的編号
- 伺服器收到請求封包,recv()函數解阻塞,傳回給用戶端一個響應,重要資料有:ACK=1,表示可以收到資訊;seq=v,伺服器位元組流資料的編号;ack=u+1,用戶端seq加1
- 伺服器調用close()函數,向用戶端發送連接配接釋放封包,封包中的重要資料有:FIN=1,seq=w,ACK=1,ack=u+1
- 用戶端收到後,回複用戶端一個資料包,ACK=1,ack=w+1,seq=u+1
3、為什麼是四次?
為什麼握手可以是三次,揮手卻是四次?因為中間第二次揮手和第三次揮手的觸發條件不同。
第二次揮手是伺服器收到了用戶端斷開連接配接的請求,此時recv()解阻塞,發送第三次揮手資訊;
第三次揮手是伺服器調用了close(),伺服器什麼時候調用close()什麼時候發送第三次揮手資訊;
是以因為觸發的條件不同,前兩次确認了用戶端的斷開,後兩次确認了伺服器的斷開。
4、圖解四次揮手
5、斷開連接配接的等待時間
- 伺服器端連接配接的完全斷開,是收到用戶端發送的第四次揮手的資料後立刻斷開
- 用戶端在發送第四次揮手的資料後,會等待2MSL時間後才會完全斷開
2MSL:MSL是最長封包段壽命,2MSL即資料包一去一回的最長時間。
第三次揮手時,伺服器給用戶端發送了資訊,同時開始了逾時時間的倒計時,用戶端收到後會傳回一個資訊給伺服器;
如果此時的網絡出現了問題,伺服器沒有在逾時時間内收到用戶端的響應,那麼伺服器就會再次發送資訊給用戶端
是以為了雙方連接配接的完全斷開,用戶端不能再發送第四次揮手資訊後直接關閉,需要等待2MSL時間,即從用戶端發送第四次揮手資訊開始,到伺服器再次發送了一個請求資訊的最長時間;
隻要伺服器收到了來自用戶端的最後确認資訊,就代表雙方可以完全斷開連接配接,此時伺服器先斷開;
用戶端隻要在2MSL時間内沒有收到伺服器的資訊,就代表伺服器已經收到了,所有,用戶端在2MSL時間後斷開連接配接。
6、圖解2MSL 等待時間
三、使用tcpdump抓取三次握手、四次揮手的封包
準備三個終端
$ # 第一個終端:啟動抓包程式
$ sudo tcpdump -# -S -n -i lo0 tcp and host 127.0.0.1 and port 8000
$ # 第二個終端:啟動服務端程式
$ nc -l 8000
$ # 第三個終端:啟動用戶端程式,發送請求
$ nc localhost 8000
此時第一個終端中就顯示了三次握手的封包資訊:
将第三個終端Ctrl+C,用戶端發起關閉,即可在第一個終端中顯示四次揮手封包資訊: