Wireshark捕獲理解TCP三次握手四次斷開

我是家碧發表於2018-04-20

1. TCP定義:

網路七層模型當中傳輸層的協議主要是TCP ,由IETF的RFC 793定義,TCP(Transimision Control Protocal)是一種可靠的、面向連線、基於位元組流的通訊協議,傳輸效率低。而傳輸層位於七層模型的中間,下面是網路層,上面的話有應用層,承上啟下,地位還是很重要的。在傳輸層中還有一種協議udp(無連線、不保證可靠性)。相比較來說tcp有以下特點:

  • 傳輸可靠,資料丟失有重傳機制
  • 資料分段打包傳輸,對每個資料編號,控制順序
  • 流量控制,避免擁塞,因為TCP連結雙方有固定大小緩衝空間。TCP的接收端只允許另一端傳送接收端緩衝區所能接納的資料
  • TCP提供全雙工服務,即資料可在同一時間雙向傳播
  • TCP將若干個位元組構成一個分組,此分組稱為報文段(Segment)。提供了一種端到端的連線。 

2. TCP資料包格式

Wireshark捕獲理解TCP三次握手四次斷開

  • 源埠號(source port) 和目標埠號(destination port)都是16位,計算機通過埠號識別訪問哪個服務,比如http服務或ftp服務,其中傳送方埠號是是隨機的,而目標埠號決定接受方由那個程式來接受並且因為是16位,所以說程式的最大埠號65535
  • 32位序列號(sequence Number) TCP用序列號對資料包進行標記,以便在到達目的地後重新重灌,假設當前的序列號為 s,傳送資料長度為 l,則下次傳送資料時的序列號為 s + l。在建立連線時通常由計算機生成一個隨機數作為序列號的初始值
  • 確認應答號(acknowledgement number) 它等於下一次應該接收到的資料的序列號。假設傳送端的序列號為 s,傳送資料的長度為 l,那麼接收端返回的確認應答號也是 s + l。傳送端接收到這個確認應答後,可以認為這個位置以前所有的資料都已被正常接收。
  • 首部長度(header length):TCP 首部的長度,單位為 4 位元組。如果沒有可選欄位,那麼這裡的值就是 5。表示 TCP 首部的長度為 20 位元組。
  • 控制位 TCP的連線、傳輸和斷開都受這六個控制位的指揮
    • PSH(push急迫位) 快取區將滿,立刻傳輸速度,表示有 DATA資料傳輸
    • RST(reset重置位) 連線斷了重新連線
    • URG(urgent緊急位) 緊急訊號
    • ACK(acknowledgement 確認)為1表示確認號
    • SYN(synchronous建立聯機,在建立TCP連線的時候使用) 同步序號位 TCP建立連線時要將這個值設為1
    • FIN傳送端完成位,表示沒有資料需要傳送了,提出斷開連線的一方把FIN置為1表示要斷開連線
  • 視窗值 說明本地可接收資料段的數目,這個值的大小是可變的。當網路通暢時將這個視窗值變大加快傳輸速度,當網路不穩定時減少這個值可以保證網路資料的可靠傳輸。它是來在TCP傳輸中進行流量控制的
  • 視窗大小(windows):表示接收緩衝區的空閒空間,16位,用來告訴TCP連結另一端自己能夠接收的最大資料長度,流量控制的機制就基於此。
  • 效驗和(checksum): 用來做差錯控制,TCP校驗和的計算包括TCP首部、資料和其它填充位元組。在傳送TCP資料段時,由傳送端計算校驗和,當到達目的地時又進行一次檢驗和計算。如果兩次校驗 和一致說明資料是正確的,否則 將認為資料被破壞,接收端將丟棄該資料
  • 緊急指標(urgent):16位,盡在 URG(urgent緊急) 控制位為 1 時有效。表示緊急資料的末尾在 TCP 資料部分中的位置。通常在暫時中斷通訊時使用(比如輸入 Ctrl + C)。

3. 三次握手

Wireshark捕獲理解TCP三次握手四次斷開

為了方便描述我們將主動發起請求的172.16.17.94:8080 主機稱為客戶端,將返回資料的主機172.16.17.94:8080稱為伺服器,以下也是。

  • 第一次握手: 建立連線。客戶端傳送連線請求,傳送SYN報文,將seq設定為0。然後,客戶端進入SYN_SEND狀態,等待伺服器的確認。
  • 第二次握手: 伺服器收到客戶端的SYN報文段。需要對這個SYN報文段進行確認,傳送ACK報文,將ack設定為1。同時,自己還要傳送SYN請求資訊,將seq為0。伺服器端將上述所有資訊一併傳送給客戶端,此時伺服器進入SYN_RECV狀態。
  • 第三次握手: 客戶端收到伺服器的ACK和SYN報文後,進行確認,然後將ack設定為1,seq設定為1,向伺服器傳送ACK報文段,這個報文段傳送完畢以後,客戶端和伺服器端都進入ESTABLISHED狀態,完成TCP三次握手。

序列號seq由雙方隨機生成,預設是0;ack = 對方序列號 + 1;seq = 對方的ack 。

三次握手是為了確認客戶端和伺服器的收發功能都是正常的。第一次確認:客戶端能發;第二次確認:伺服器能收能發;第三次確認:客戶端能收。

4. 資料傳輸

Wireshark捕獲理解TCP三次握手四次斷開

  • 客戶端先向伺服器傳送資料,該資料包是長度為159的資料。
  • 伺服器收到報文後, 也向客戶端傳送了一個資料進行確認(ACK),並且返回客戶端要請求的資料,資料的長度為111,將seq設定為1,ack設定為160(1 + 159)。
  • 客戶端收到伺服器返回的資料後進行確認(ACK),將seq設定為160, ack設定為112(1 + 111)。

ack = 對方的序列號 + 傳送的資料長度 ; seq = 對方的ack 。

5. 四次揮手

    Wireshark捕獲理解TCP三次握手四次斷開

  • 第一次揮手:客戶端向伺服器傳送一個FIN報文段,將設定seq為160和ack為112,;此時,客戶端進入 FIN_WAIT_1狀態,這表示客戶端沒有資料要傳送伺服器了,請求關閉連線;
  • 第二次揮手:伺服器收到了客戶端傳送的FIN報文段,向客戶端回一個ACK報文段,ack設定為1,seq設定為112;伺服器進入了CLOSE_WAIT狀態,客戶端收到伺服器返回的ACK報文後,進入FIN_WAIT_2狀態;
  • 第三次揮手:伺服器會觀察自己是否還有資料沒有傳送給客戶端,如果有,先把資料傳送給客戶端,再傳送FIN報文;如果沒有,那麼伺服器直接傳送FIN報文給客戶端。請求關閉連線,同時伺服器進入LAST_ACK狀態;
  • 第四次揮手:客戶端收到伺服器傳送的FIN報文段,向伺服器傳送ACK報文段,將seq設定為161,將ack設定為113,然後客戶端進入TIME_WAIT狀態;伺服器收到客戶端的ACK報文段以後,就關閉連線;此時,客戶端等待2MSL後依然沒有收到回覆,則證明Server端已正常關閉,客戶端也可以關閉連線了。

 注意:在握手和揮手時確認號應該是對方序列號加1,傳輸資料時則是對方序列號加上對方攜帶應用層資料的長度。   

6. 問題

  1. 為什麼需要三次握手? 確保雙方收發都是正常的
  2. 為什麼需要四次揮手? 雙方資料傳送完畢,都認為可以斷開
  3. 為什麼需要等待? A向B發的FIN可能丟失
  4. 為什麼握手是三次,但揮手卻是四次? 當Server端收到FIN報文時,很可能並不會立即關閉SOCKET

                                                                                                                                

wireshark抓包工具安裝

wireshark下載地址https://www.wireshark.org/download.html

注意:本機訪問本機的服務,wireshark是捕獲不到的。

第一次用wireshark出現這個報錯是因為wireshark沒有裝全,記得裝wincap。

Wireshark捕獲理解TCP三次握手四次斷開

Wireshark捕獲理解TCP三次握手四次斷開

wireshark抓包開始

三次握手

Wireshark捕獲理解TCP三次握手四次斷開

172.18.254.177為客戶 111.13.2.158為服務端

1、主動開啟。傳送SYN,協商window size 、TCP MSS seq=0 len=0 MSS=1460 win=65535最大視窗大小

客戶端為syn_sent

服務端為syn_recv

2、接收到syn。回覆syn ack seq=0 ack=1=0+1 確認自己的最大win=14480 MSS=1460

客戶端為established

服務端為syn_recv

3、接到到syn 回覆ack seq=1 ack=1=0+1 至此三次握手成功建立。

客戶端為established

服務端為established

四次斷開

Wireshark捕獲理解TCP三次握手四次斷開

1、主動關閉,傳送fin。Seq=328

服務端狀態為fin_wait1

客戶端狀態為closed_wait

2、客戶端傳送確認ack ack=329=328+1

服務端狀態為fin_wait2

3、客戶端傳送fin seq=133

客戶端狀態為last_ack

服務端狀態為time_wait

4、服務端傳送ack ack=134=133+1

客戶端狀態closed

服務端狀態closed

資料包ACK=segment len+seq = 下一個要接收的資料包的seq

Wireshark捕獲理解TCP三次握手四次斷開

圖1

Wireshark捕獲理解TCP三次握手四次斷開

圖2

Wireshark捕獲理解TCP三次握手四次斷開

圖3

由圖1 資料包情況可以看出 359 seq=1441 segment len=1440 所以下一個回包的ack=1441+1440=2881 從圖2中可以確認ack確實為2881.

圖2 資料包情況可以看出 360 seq=349 segment len=0 所以下一個回包的ack=349+0=349,從圖3可以確認ack確實為349.


圖1 359 的ack=349 則圖2 350 的seq=349 ack=2881 推斷圖3 361的seq=2881 .

一條完整會話(session)指的是,相同的傳輸協議中兩個不同IP之間的兩個不同埠的互相通訊,如果IP或埠變化剛屬於不同的會話,其seq和ack也是相互獨立的,沒有任何關聯。

win 65535:視窗大小是65535位元組。視窗大小指的是對方在同一時間點內能夠接收到的位元組數,網路頻寬越大視窗越大,能傳送的資料就越大。網路頻寬越小視窗越小,能傳送的資料就越小。http協議是83位元組。TCP segment len == http len。




相關文章