三次握手,四次揮手 具體發送的報文和狀態都要掌握(阿里)

若是想了解HTTP的協議結構,原理,post,get的區別(阿里面試題目),請參考:HTTP協議 結構,get post 區別(阿里面試) 

可是若是想進入阿里的話,仍是看本文理解TCP的三次握手和四次揮手,發送的報文和狀態都要掌握,阿里問了好幾回了。html

七層協議四層協議 參考:七層協議和四層協議 面試

TCP報文格式


TCP報文格式1.jpg

16位源端口號:16位的源端口中包含初始化通訊的端口。源端口和源IP地址的做用是標識報文的返回地址。shell

16位目的端口號:16位的目的端口域定義傳輸的目的。這個端口指明報文接收計算機上的應用程序地址接口。編程

32位序號:32位的序列號由接收端計算機使用,從新分段的報文成最初形式。當SYN出現,序列碼其實是初始序列碼(Initial Sequence Number,ISN),而第一個數據字節是ISN+1。這個序列號(序列碼)可用來補償傳輸中的不一致。windows

32位確認序號:32位的序列號由接收端計算機使用,重組分段的報文成最初形式。若是設置了ACK控制位,這個值表示一個準備接收的包的序列碼。bash

4位首部長度:4位包括TCP頭大小,指示何處數據開始。服務器

保留(6位):6位值域,這些位必須是0。爲了未來定義新的用途而保留。網絡

標誌:6位標誌域。表示爲:緊急標誌、有意義的應答標誌、推、重置鏈接標誌、同步序列號標誌、完成發送數據標誌。按照順序排列是:URG、ACK、PSH、RST、SYN、FIN。socket

16位窗口大小:用來表示想收到的每一個TCP數據段的大小。TCP的流量控制由鏈接的每一端經過聲明的窗口大小來提供。窗口大小爲字節數,起始於確認序號字段指明的值,這個值是接收端正指望接收的字節。窗口大小是一個16字節字段,於是窗口大小最大爲65535字節。tcp

16位校驗和:16位TCP頭。源機器基於數據內容計算一個數值,收信息機要與源機器數值 結果徹底同樣,從而證實數據的有效性。檢驗和覆蓋了整個的TCP報文段:這是一個強制性的字段,必定是由發送端計算和存儲,並由接收端進行驗證的。

16位緊急指針:指向後面是優先數據的字節,在URG標誌設置了時纔有效。若是URG標誌沒有被設置,緊急域做爲填充。加快處理標示爲緊急的數據段。

選項:長度不定,但長度必須爲1個字節。若是沒有選項就表示這個1字節的域等於0。

數據:該TCP協議包負載的數據。

TCP標誌位:

TCP共有6個標誌位,分別是:

  • SYN(synchronous),創建聯機。
  • ACK(acknowledgement),確認。
  • PSH(push),傳輸。
  • FIN(finish),結束。
  • RST(reset),重置。
  • URG(urgent),緊急。 

URG:緊急標誌。緊急標誌爲"1"代表該位有效。

ACK:確認標誌。代表確認編號欄有效。大多數狀況下該標誌位是置位的。TCP報頭內的確認編號欄內包含的確認編號(w+1)爲下一個預期的序列編號,同時提示遠端系統已經成功接收全部數據。

PSH:推標誌。該標誌置位時,接收端不將該數據進行隊列處理,而是儘量快地將數據轉由應用處理。在處理Telnet或rlogin等交互模式的鏈接時,該標誌老是置位的。

RST:復位標誌。用於復位相應的TCP鏈接。

SYN:同步標誌。代表同步序列編號欄有效。該標誌僅在三次握手創建TCP鏈接時有效。它提示TCP鏈接的服務端檢查序列編號,該序列編號爲TCP鏈接初始端(通常是客戶端)的初始序列編號。在這裏,能夠把TCP序列編號看做是一個範圍從0到4,294,967,295的32位計數器。經過TCP鏈接交換的數據中每個字節都通過序列編號。在TCP報頭中的序列編號欄包括了TCP分段中第一個字節的序列編號。

FIN:結束標誌。

TCP三次握手

所謂三次握手(Three-Way Handshake)即創建TCP鏈接,就是指創建一個TCP鏈接時,須要客戶端和服務端總共發送3個包以確認鏈接的創建。在socket編程中,這一過程由客戶端執行connect來觸發,整個流程以下圖所示:


TCP三次握手.png

(1)第一次握手:Client將標誌位SYN置爲1,隨機產生一個值seq=J,並將該數據包發送給Server,Client進入SYN_SENT狀態,等待Server確認。

(2)第二次握手:Server收到數據包後由標誌位SYN=1知道Client請求創建鏈接,Server將標誌位SYN和ACK都置爲1,ack=J+1,隨機產生一個值seq=K,並將該數據包發送給Client以確認鏈接請求,Server進入SYN_RCVD狀態。

(3)第三次握手:Client收到確認後,檢查ack是否爲J+1,ACK是否爲1,若是正確則將標誌位ACK置爲1,ack=K+1,並將該數據包發送給Server,Server檢查ack是否爲K+1,ACK是否爲1,若是正確則鏈接創建成功,Client和Server進入ESTABLISHED狀態,完成三次握手,隨後Client與Server之間能夠開始傳輸數據了。

簡單來講,就是

一、創建鏈接時,客戶端發送SYN包(SYN=i)到服務器,並進入到SYN-SEND狀態,等待服務器確認

二、服務器收到SYN包,必須確認客戶的SYN(ack=i+1),同時本身也發送一個SYN包(SYN=k),即SYN+ACK包,此時服務器進入SYN-RECV狀態

三、客戶端收到服務器的SYN+ACK包,向服務器發送確認報ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手,客戶端與服務器開始傳送數據。

SYN網絡攻擊:

在三次握手過程當中,Server發送SYN-ACK以後,收到Client的ACK以前的TCP鏈接稱爲半鏈接(half-open connect),此時Server處於SYN_RCVD狀態,當收到ACK後,Server轉入ESTABLISHED狀態。SYN攻擊就是Client在短期內僞造大量不存在的IP地址,並向Server不斷地發送SYN包,Server回覆確認包,並等待Client的確認,因爲源地址是不存在的,所以,Server須要不斷重發直至超時,這些僞造的SYN包將產時間佔用未鏈接隊列,致使正常的SYN請求由於隊列滿而被丟棄,從而引發網絡堵塞甚至系統癱瘓。SYN攻擊時一種典型的DDOS攻擊,檢測SYN攻擊的方式很是簡單,即當Server上有大量半鏈接狀態且源IP地址是隨機的,則能夠判定遭到SYN攻擊了,使用以下命令可讓之現行:

 #netstat -nap | grep SYN_RECV 

檢測: 
SYN攻擊時一種典型的DDOS攻擊,檢測SYN攻擊的方式很是簡單,即當Server上有大量半鏈接狀態且源IP地址是隨機的,則能夠判定遭到SYN攻擊了。windows下打開cmd,輸入命令:」netstat -n -p TCP「,查看是否有大量的」SYN_RECEIVED「狀態。

如下圖片是代表正常的。 

TCP四次揮手

所謂四次揮手(Four-Way Wavehand)即終止TCP鏈接,就是指斷開一個TCP鏈接時,須要客戶端和服務端總共發送4個包以確認鏈接的斷開。在socket編程中,這一過程由客戶端或服務端任一方執行close來觸發,整個流程以下圖所示:


TCP四次揮手.png

因爲TCP鏈接時全雙工的,所以,每一個方向都必需要單獨進行關閉,這一原則是當一方完成數據發送任務後,發送一個FIN來終止這一方向的鏈接,收到一個FIN只是意味着這一方向上沒有數據流動了,即不會再收到數據了,可是在這個TCP鏈接上仍然可以發送數據,直到這一方向也發送了FIN。首先進行關閉的一方將執行主動關閉,而另外一方則執行被動關閉,上圖描述的便是如此。

(1)第一次揮手:Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態。(狀態位FIN=1,發送seq=J)

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

(3)第三次揮手:Server發送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態。(狀態位FIN=1,發送seq=K)

(4)第四次揮手:Client收到FIN後,Client進入TIME_WAIT狀態,接着發送一個ACK給Server,確認序號爲收到序號+1,Server進入CLOSED狀態,完成四次揮手。(狀態位ACK=1,ack=K+1)

注意此時客戶端並未進入CLOSED狀態,爲了防止服務延遲,須要等待2MSL的時間,而後進入CLOSED狀態,由於若是客戶端直接進入CLOSED了,若是網絡異常,客戶端就不能重重發數據。

 

爲何創建鏈接是三次握手,而關閉鏈接倒是四次揮手呢?

這是由於服務端在LISTEN狀態下,收到創建鏈接請求的SYN報文後,把ACK和SYN放在一個報文裏發送給客戶端。而關閉鏈接時,當收到對方的FIN報文時,僅僅表示對方再也不發送數據了可是還能接收數據,己方也未必所有數據都發送給對方了,因此己方能夠當即close,也能夠發送一些數據給對方後,再發送FIN報文給對方來表示贊成如今關閉鏈接,所以,己方ACK和FIN通常都會分開發送。 

爲何TIME_WAIT狀態須要通過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?

緣由有二:
1、保證TCP協議的全雙工鏈接可以可靠關閉
2、保證此次鏈接的重複數據段從網絡中消失

先說第一點,若是Client直接CLOSED了,那麼因爲IP協議的不可靠性或者是其它網絡緣由,致使Server沒有收到Client最後回覆的ACK。那麼Server就會在超時以後繼續發送FIN,此時因爲Client已經CLOSED了,就找不到與重發的FIN對應的鏈接,最後Server就會收到RST而不是ACK,Server就會覺得是鏈接錯誤把問題報告給高層。這樣的狀況雖然不會形成數據丟失,可是卻致使TCP協議不符合可靠鏈接的要求。因此,Client不是直接進入CLOSED,而是要保持TIME_WAIT,當再次收到FIN的時候,可以保證對方收到ACK,最後正確的關閉鏈接。

再說第二點,若是Client直接CLOSED,而後又再向Server發起一個新鏈接,咱們不能保證這個新鏈接與剛關閉的鏈接的端口號是不一樣的。也就是說有可能新鏈接和老鏈接的端口號是相同的。通常來講不會發生什麼問題,可是仍是有特殊狀況出現:假設新鏈接和已經關閉的老鏈接端口號是同樣的,若是前一次鏈接的某些數據仍然滯留在網絡中,這些延遲數據在創建新鏈接以後纔到達Server,因爲新鏈接和老鏈接的端口號是同樣的,又由於TCP協議判斷不一樣鏈接的依據是socket pair,因而,TCP協議就認爲那個延遲的數據是屬於新鏈接的,這樣就和真正的新鏈接的數據包發生混淆了。因此TCP鏈接還要在TIME_WAIT狀態等待2倍MSL,這樣能夠保證本次鏈接的全部數據都從網絡中消失。

 
這個問題也很好理解,當客戶端最終告訴服務器端斷開確認的時候,他不知道本身的發出的指令是否能準確的一次性被服務器接收。假如服務器沒有接收到(這已經耗費了一個報文的最大通訊時間了),服務器端將會從新發起一個結束通話的指令(FIN)到客戶端,客戶端又接收到了服務器發來的結束通訊指令將繼續給服務器進行一個確認,有人會說那要是客戶端發出的確認信息服務端沒收到,而服務端重發的斷開指令客戶端也沒收到怎麼辦,說實話我也無奈,遇到這種狀況我們乾脆認爲網確實不行了。

TCP/IP協議三次握手和四次揮手大白話解說 

 前言 

TCP(Transmission Control Protocol)網絡傳輸控制協議,是一種面向鏈接的、可靠的、基於字節流的傳輸層通訊協議,數據傳輸前創建鏈接的工做要通過三次握手,數據傳輸後斷開鏈接的工做要通過四次揮手。

工做過程

三次握手創建鏈接闡述:

第一次握手:客戶端要和服務端進行通訊,首先要告知服務端一聲,遂發出一個SYN=1的鏈接請求信號,」服務端哥哥,我想給你說說話」。

第二次握手:當服務端接收到客戶端的鏈接請求,此時要給客戶端一個確認信息,」我知道了(ACK),我這邊已經準備好了,你如今能連嗎(SYN)」。

第三次握手:當客戶端收到了服務端的確認鏈接信息後,要禮貌的告知一下服務端,「好的,我們開始聯通吧(ACK)」。

到此整個創建鏈接的過程已經結束,接下來就是雙方你一句我一句甚至同時交流傳遞信息的過程了。

四次揮手斷開鏈接闡述:

第一次揮手:雙方交流的差很少了,此時客戶端也已經結尾了,接下來要斷開通訊鏈接,因此告訴服務端「我說完了(FIN)」,此時自身造成等待結束鏈接的狀態。

第二次揮手:服務端知道客戶端已經沒話說了,服務端此時還有兩句內心話要給客戶端說,「我知道你說完了(ACK),我再給你說兩句,&*……%¥」。

第三次揮手:此時客戶端洗耳恭聽繼續處於等待結束的狀態,服務器端也說完了,自身此時處於等待關閉鏈接的狀態,並對告訴客戶端,「我說完了,我們斷了吧(FIN)」。

第四次揮手:客戶端收知道服務端也說完了,也要告訴服務端一聲(ACK),由於鏈接和斷開要雙方都按下關閉操做才能斷開,客戶端同時又爲本身定義一個定時器,由於不知道剛纔說的這句話能不能準確到達服務端(網絡不穩定或者其餘因素引發的網絡緣由),默認時間定爲兩個通訊的最大時間之和,超出這個時間就默認服務器端已經接收到了本身的確認信息,此時客戶端就關閉自身鏈接,服務器端一旦接收到客戶端發來的肯定通知就馬上關閉服務器端的鏈接。

到此爲止雙方整個通訊過程就此終結。這裏要聲明一下:斷開連接不必定就是客戶端,誰均可以先發起斷開指令,另外客戶端和服務端是沒有固定標準的,誰先發起請求誰就是客戶端。 

附加

 在TIME_WAIT狀態中,若是TCP client端最後一次發送的ACK丟失了,它將從新發送。TIME_WAIT狀態中所須要的時間是依賴於實現方法的。典型的值爲30秒、1分鐘和2分鐘。等待以後鏈接正式關閉,而且全部的資源(包括端口號)都被釋放。 

 參考:TCP/IP協議三次握手和四次揮手大白話解說

 參考:TCP協議詳解 

相關文章
相關標籤/搜索