計算機網絡之-------TCP 三次握手和四次揮手

1.TCP的概念

       TCP(Transmission Control Protocol) 傳輸控制協議,是一種面向連接的、可靠的、基於字節流的傳輸控制協議。TCP就是一個雙向通信的規範標準。

2 TCP頭部報文

   

   1)source port   和destination port

         source port 就是源端口號,具體指本地端口號,destination port 就是遠程端口號。

       一個數據包被解封裝成數據段後就會涉及到連接上層協議的端口號問題。簡單的說我們本地發送方有多種端口,接收方(遠程)也會有多種端口, source port和destination port就分別代表從哪個規定的串口發送到對方接受的窗口。兩者之間一一對應。不同的應用程序有不同的端口。比如發送方的微信端口8080對應着接受方的微信端口8080。

     說明:應用程序的端口號和應用程序所在主機的IP地址統稱爲套接字(socket)。IP:端口號,在互聯網上socket唯一標識每一個應用程序,源端口+源IP+目的IP稱爲「套接字對」,一個套接字就是一個連接,一個客服端與服務器之間的連接。

  2)Sequence Number 

       初始序列號,用於TCP通信過程中某一傳輸方向上字節流的每個字節編號,爲了確保數據通信的有序性,避免網絡中亂序的問題。接收端根據這個編號進行確認,保證分割數據段在原始數據包的位置。每個字段在傳送中用序列號來標記自己的位置,而這個字段就是用來完成雙方傳輸中確保字段原始位置是按照傳輸順序的。

     說明:初始的序列號是自己定的,而後續的序列號由對端的ACK確定。SN_x=ACK_y(x的序列號等於y發送給x的ACK)。

3)Acknowledgement Number

     ack確認序列號,接收確認端所期望收到的下一個序列號確認序列號應當是上次已經成功收到的數據字節序號加1,只有當標誌位的ACK標誌爲1時,該確認序列號纔有效,主要用來解決不丟包的問題。

   如果確認序列號=N,那麼就表示序號N-1爲止的所有數據都能已經正確收到。

   數據傳輸是一段一段的,都是有序列號進行標識的,因此,接收端每接收一段,之後想要的下一段的序列號稱爲確認序列號。

4)TCP Flag

     TCP 首部有6個標誌比特,他們中多個可同時被設置爲1。主要用來操控TCP的狀態機,依次爲URG,ACK,PSH,RST,SYN,FIN。

    ACK

        ACK指發送端發送數據到接收端,發送的時候ACK爲0,表示接收端還沒應答,一旦被接收端接收數據之後,就將ACK置爲1,發送端接收之後,就知道接收端已經接收了數據。

      ACK標誌表示應答域有效,就是說TCP應答號將會包含在TCP數據包中:取值爲0和1,1代表應答域有效,否則爲0,

 SYN

    同步序列號,是TCP握手發送的第一個數據包。SYN用來建立TCP的連接,SYN標識位和ACK標識位搭配使用,當連接請求時,SYN爲1,ACK爲0,在連接被響應之後,SYN爲1,ACK爲1;這個標識的數據包經常被用來進行端口的掃描,掃描者發送一個只有SYN的數據包,如果對方相應了一個數據包回來,就表示這個主機存在這個端口。

      過程爲:發送端 SYN=1,ACK=0,發送端向接收端發送請求消息,接收端收到SYN=1,ACK=0的數據包,就知道發送端想給他發送數據,這時接收端將SYN=1,ACK=1,將其迴應給發送端,告訴發送端,我已經準備好了,以開始發送消息吧。

  FIN

    FIN表示發送端已經發送到數據末尾,就是說雙方的數據已經傳輸完成,沒有數據可以傳送了。發送FIN標識位的TCP數據包後,連接就會被斷開,這個標識的數據包也經常用於端口掃描。

   當發送端只剩一個數據時,需要告訴接收端我這裏沒有數據了,數據發送完了,就用FIN=1來標識一下,接收端收到FIN=1的標識之後,就知道這是最後的數據,接收這個數據之後,就將連接斷開。

5)Window size

   滑動窗口大小,用來進行流量控制。

TCP滑動窗口:

  RTT:發送一個數據包到收到對方迴應的ACK,所花費的時間。

 RTO:重傳時間間隔,TCP在發送一個數據包之後,會啓動一個重傳定時器,RTO就是定時器的重傳時間。如果收到了對方的ACK,那麼RTO就失效,如果沒有收到,RTO重傳定時器的時間到了之後,就需要重傳數據包。RTO通過RTT計算得出。

 TCP使用滑動窗口做流量控制與亂序重排:

    1.保證了TCP的可靠性。

   2.保證TCP的流控特性。

    流量控制:Window size 用於接收方通知發送方,告訴發送發自己還有多少緩衝區可以接收數據,發送方就會根據接收方的處理能力來接收數據,不會導致接收方處理不過來數據,這就是流量控制。

 

       LastByteAcked: 連續被接收端接收並已經返回的確認序列號的最大值。

      LastByteSend:已經發送的最後一個字節的位置(未收到ACK確認)

     LastByteWritten:上層應用已經寫完的的最後一個字節的位置。

     LastByteRead:上層應用已經讀完的最後一個字節的位置。

     NextByteExpected:接收到發送端的連續序列號的最大值的位置,接收到沒有反饋確認ACK

   LastByteRcved:已經收到的最後一個字節的位置。

    AdvertisedWindow:接收端還能接收的窗口大小。

   EffectiveWindow:發送端還需要發送的窗口大小。

  

 

     TCP會話的發送方分爲四個區域,發送已經接收到ACK的數據段、發送沒有接收到ACK的數據段、沒有發送準備發送的數據段、沒有發送不能發送的數據段。

     其中發送沒有接收到ACK的數據段、沒有發送準備發送的數據段的長度和,稱爲滑動窗口,假設滑動窗口的長度爲序列號32-51之間的數據段。其中32-40爲發送沒有接收到ACK的數據段,41-51位沒有發送準備發送的數據段。這時當發送方收到接收方發來的ACK=36時(ACK只能是32-40之間的數據),滑動窗口就會移動到36-55的區域。這時52-55原來屬於沒有發送不能發送的數據段,在滑動窗口移動之後,52-55數據段就變成了沒有發送準備發送的數據段。

  

 

3 TCP的三次握手

  

     初始狀態:客戶端處於close(關閉)狀態。服務器處於listen(監聽)狀態。

  1)第一次握手:建立連接時,客服端發動SYN包(seq=x)到服務器,並進入SYN_SEND狀態,等待服務器確認。

           客戶端發送請求報文將同步序列號SYN=1,初始化序列號seq=x,發送給服務器,在發送完成之後,客戶端就進入SYN_send狀態(發送等待轉態)。

   2)第二次握手:服務器收到SYN包,必須確認客戶端的SYN(ack=x+1),同時自己也要發送一個SYN包(seq=y),即SYN+ACK包,此時服務器進入SYN_RECEVICE狀態。

        服務器收到客服端發送的SYN請求報文之後,如果服務器同意連接,會將自己的同步序列號SYN(服務器端)=1、初始化序列號seq=y、確定序列號(期望下次從客戶端收到的數據包)ack=x+1、確認號ACK=1,作爲應答報文,之後服務器處於SYN_Receive狀態(確認接收狀態)。

     3)第三次握手:客服端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1).此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。

           客戶端接收到服務器端的SYN和ACK之後,知道可以下次發送下一序列的數據包了,然後發動確定序列號ack=y+1和數據包的序列號seq=x+1、確認號ACK=1,作爲應該報文。之後客服端進入established(確認連接狀態)。

4 爲什麼要三次握手

    防止服務器端的一直等待而浪費資源。

   爲 了防止已失效的連接請求報文段突然又傳送到了服務端,因而產生錯誤。如果此時客戶端發送的延遲的握手信息服務器收到,然後服務器進行響應,認爲客戶端要和它建立連接,此時客戶端並沒有這個意思,但 server 卻以爲新的運輸連接已經建立,並一直等待 client 發來數據。這樣,server 的很多資源就白白浪費掉了。

  爲什麼需要三次握手才能建立連接?

      爲了初始化Sequence Number 的初始值。

建立連接後,client出現故障怎麼辦?

   保活機制:

         (1)向對方發送保活探測報文,如果沒有收到響應就繼續發送。

        (2) 嘗試次數達到保活探測數仍然沒有收到響應就會斷開連接

  

 

5 TCP的四次揮手

     初始化狀態:客戶端和服務器都處於連接階段。下面進行四次揮手端來連接。

 1)第一次揮手:client發送一個FIN,用來關閉client到sever的數據傳送,Client進入FIN_WAIT_1狀態。

         第一次揮手客戶端和服務器都可以發起,因爲TCP是雙全工的。

         假設客戶端發送的數據已經發送完畢,發送FIN=1,告訴服務器,客戶端所有的數據都已近發送完畢了,服務器可以關閉接收了。但是這時如果服務器還有數據要發送給客戶端,客戶端還可以繼續接收數據,此時的客戶端處於FIN=1等待服務器確認釋放連接狀態(FIN_Wait)。

  2)第二次揮手:Sever收到FIN後,發送一個ACK給Client,確認序列號爲收到序列號+1(與SYN相同,一個FIN佔用一個序號),Sever進入CLOSE_WAIT狀態。

       服務器接收到客戶端的釋放連接請求後,知道客戶端沒有數據要發送給自己了,之後,服務器就會發送一個ACK=1,來告訴客戶端已經接收到給我發送的消息了。此時的服務器處於CLOSE_WAIT等待關閉狀態。

3)第三次揮手:Sever發送一個FIN,用來關閉Server到Client的數據傳送,Sever進入LAST_WAIT轉態。

      此時的服務器已經把所有的數據發送完了,然後向客服端發送一個FIN=1,用來告訴客戶端,服務器的數據已經全部發送完畢,客戶端你也可以關閉接收數據連接了。此時的服務器處於確定關閉狀態(LAST_ACK),來等待客戶端確定是否收到了自己的請求。

 4)第四次揮手:Client收到FIN之後,Client進入TIME_WAIT狀態,接着發送一個ACK給Serve,確認序號爲收到序號+1,Sever進入CLOSED狀態,完成四次揮手

    此時如果客戶端收到了服務器發送的消息之後,就發送一個ACK=1,告訴服務器,客戶端已經收到了你的消息。這裏會有一個2MSl的延遲等待。

   對應這樣一種情況,最後客戶端發送的ACK = 1給服務端的過程中丟失了,服務端沒收到,服務端怎麼認爲的?我已經發送完數據了,怎麼客戶端沒回應我?是不是中途丟失了?然後服務端再次發起斷開連接的請求,一個來回就是2MSL,這裏的兩個來回由那一個來回組成的?

   客戶端給服務端發送的ACK = 1丟失,服務端等待 1MSL沒收到,然後重新發送消息需要1MSL。如果再次接收到服務端的消息,則重啓2MSL計時器,發送確認請求。客戶端只需等待2MSL,如果沒有再次收到服務端的消息,就說明服務端已經接收到自己確認消息;此時雙方都關閉的連接,TCP 四次分手完畢。

爲什麼會用TIME_WAIT狀態?

   1.確保有足夠的時間讓對方收到ACK包

   2、避免新舊連接混淆

爲什麼需要四次揮手才能斷開連接?

  因爲TCP是全雙工的,發送方和接收方都需要FIN報文和ACK報文。