【linux】關於TCP三向交握和四次揮手,linuxtcp三次揮手

來源:互聯網
上載者:User

【linux】關於TCP三向交握和四次揮手,linuxtcp三次揮手
1、TCP是什麼

關於OSI的七層模型

  • TCP在第四層——Transport層,第四層的資料叫Segment-》報文
  • IP在第三層——Network層,在第三層上的資料叫Packet-》資料包
  • ARP在第二層——Data Link層;在第二層上的資料,我們把它叫Frame-》幀

資料從應用程式層發下來,會在每一層都會加上頭部資訊,進行封裝,然後再發送到資料接收端,就是每個資料都會經過資料的封裝和解鎖裝的過程。

wireshark抓到的包與對應的協議層如所示

 

  • Frame 36441: 物理層的資料幀概況
  • Ethernet II: 資料連結層乙太網路幀頭部資訊
  • Internet Protocol Version 4: IPV4 網路層
  • Transmission Control Protocol: TCP 傳輸層
  • Hypertext Transfer Protocol: 應用程式層 HTTP

在OSI七層模型中,每一層的作用和對應的協議如下:

wireshark抓到的傳輸層的報文

TCP是一個協議,那這個協議是如何定義的,它的資料格式是什麼樣子的呢

上面就是TCP協議頭部的格式,由於它太重要了,是理解其它內容的基礎,下面就將每個欄位的資訊都詳細的說明一下

  • Source Port和Destination Port:分別佔用16位,表示源連接埠號碼和目的連接埠號碼;用於區別主機中的不同進程,而IP地址是用來區分不同的主機的,源連接埠號碼和目的連接埠號碼配合上IP首部中的源IP地址和目的IP地址就能唯一的確定一個TCP串連;
  • Sequence Number:用來標識從TCP發端向TCP收端發送的資料位元組流,它表示在這個報文段中的的第一個資料位元組在資料流中的序號;主要用來解決網路報亂序的問題;
  • Acknowledgment Number:32位確認序號包含發送確認的一端所期望收到的下一個序號,因此,確認序號應當是上次已成功收到資料位元組序號加1。不過,只有當標誌位中的ACK標誌為1時該確認序號的欄位才有效。主要用來解決不丟包的問題;
  • Offset:給出首部中32 bit字的數目,需要這個值是因為任選欄位的長度是可變的。這個欄位佔4bit(最多能表示15個32bit的的字,即4*15=60個位元組的首部長度),因此TCP最多有60位元組的首部。然而,沒有任選欄位,正常的長度是20位元組;
  • TCP Flags:TCP首部中有6個標誌位元,它們中的多個可同時被設定為1,主要是用於操控TCP的狀態機器的,依次為URG,ACK,PSH,RST,SYN,FIN。每個標誌位的意思如下:
    • URG:此標誌表示TCP包的緊急指標域有效,用來保證TCP串連不被中斷,並且督促中介層裝置要儘快處理這些資料;
    • ACK:此標誌表示應答域有效,就是說前面所說的TCP應答號將會包含在TCP資料包中;有兩個取值:0和1,為1的時候表示應答域有效,反之為0;
    • PSH:這個標誌位表示Push操作。所謂Push操作就是指在資料包到達接收端以後,立即傳送給應用程式,而不是在緩衝區中排隊;
    • RST:這個標誌表示串連複位請求。用來複位那些產生錯誤的串連,也被用來拒絕錯誤和非法的資料包;
    • SYN:表示同步序號,用來建立串連。SYN標誌位和ACK標誌位搭配使用,當串連請求的時候,SYN=1,ACK=0;串連被響應的時候,SYN=1,ACK=1;這個標誌的資料包經常被用來進行連接埠掃描。掃描者發送一個只有SYN的資料包,如果對方主機響應了一個資料包回來 ,就表明這台主機存在這個連接埠;但是由於這種掃描方式只是進行TCP三向交握的第一次握手,因此這種掃描的成功表示被掃描的機器不很安全,一台安全的主機將會強制要求一個串連嚴格的進行TCP的三向交握;
    • FIN: 表示發送端已經達到資料末尾,也就是說雙方的資料傳送完成,沒有資料可以傳送了,發送FIN標誌位的TCP資料包後,串連將被斷開。這個標誌的資料包也經常被用於進行連接埠掃描。
  • Window:視窗大小,也就是有名的滑動視窗,用來進行流量控制;這是一個複雜的問題,這篇博文中並不會進行總結的
關於三向交握和四次揮手

wireshark 抓包

一個反向 Proxy中的網路連接

 

2、三向交握又是什麼

TCP是連線導向的,無論哪一方向另一方發送資料之前,都必須先在雙方之間建立一條串連。在TCP/IP協議中,TCP協議提供可靠的串連服務,串連是通過三向交握進行初始化的。三向交握的目的是同步串連雙方的序號和確認號並交換 TCP視窗大小資訊。

第一次握手:建立串連。用戶端發送串連請求報文段,將SYN位置為1,Sequence Number為x;然後,用戶端進入SYN_SEND狀態,等待伺服器的確認;

第二次握手:伺服器收到SYN報文段。伺服器收到用戶端的SYN報文段,需要對這個SYN報文段進行確認,設定Acknowledgment Number為x+1(Sequence Number+1);同時,自己自己還要發送SYN請求資訊,將SYN位置為1,Sequence Number為y;伺服器端將上述所有資訊放到一個報文段(即SYN+ACK報文段)中,一併發送給用戶端,此時伺服器進入SYN_RECV狀態;

第三向交握:用戶端收到伺服器的SYN+ACK報文段。然後將Acknowledgment Number設定為y+1,向伺服器發送ACK報文段,這個報文段發送完畢以後,用戶端和伺服器端都進入ESTABLISHED狀態,完成TCP三向交握。

完成了三向交握,用戶端和伺服器端就可以開始傳送資料,使用tcpdump在伺服器上抓包,可以看到

[root@dev ~]# tcpdump -i lo  port 12000tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes22:58:54.952917 IP localhost.48383 > localhost.entextxid: Flags [S], seq 439289121, win 65495, options [mss 65495,sackOK,TS val 4017863386 ecr 0,nop,wscale 7], length 022:58:54.952928 IP localhost.entextxid > localhost.48383: Flags [S.], seq 3569639229, ack 439289122, win 65483, options [mss 65495,sackOK,TS val 4017863386 ecr 4017863386,nop,wscale 7], length 022:58:54.952938 IP localhost.48383 > localhost.entextxid: Flags [.], ack 1, win 512, options [nop,nop,TS val 4017863386 ecr 4017863386], length 0

我們可以看到

client => server   seq = 439289121 flags = S  

server=>client  ack=seq+1=439289122 , seq = 3569639229 flags = S

client=>server ack=1 flags = 空

  • Win:視窗欄位明確指出現在允許對方發送的資料量(經常變化)
  • MSS(Maximum Segment Size):最大報文段長度,即每個TCP報文段中的資料欄位的最大長度.這裡需要在握手的時候進行協商,雙方都給出MSS,最後以最小MSS確定為最終的MSS.IP資料報最大傳輸單位為MTU(Maximum Transmission Unit,Effect of short board),對於大多數使用乙太網路的區域網路來說,MTU=1500。MSS往往基於MTU計算出來,通常MSS=MTU-sizeof(IP Header)-sizeof(TCP Header)=1500-20-20=1460
  • sackOK 確認欄位

串連建立之後,我們在發送一條命令

23:08:44.906783 IP localhost.48387 > localhost.entextxid: Flags [P.], seq 1:8, ack 1, win 512, options [nop,nop,TS val 4018453340 ecr 4018450643], length 723:08:44.906802 IP localhost.entextxid > localhost.48387: Flags [.], ack 8, win 512, options [nop,nop,TS val 4018453340 ecr 4018453340], length 023:08:44.906997 IP localhost.entextxid > localhost.48387: Flags [P.], seq 1:1174, ack 8, win 512, options [nop,nop,TS val 4018453340 ecr 4018453340], length 117323:08:44.907008 IP localhost.48387 > localhost.entextxid: Flags [.], ack 1174, win 531, options [nop,nop,TS val 4018453340 ecr 4018453340], length 0
3、那四次分手呢?

由於TCP串連是全雙工系統的,因此每個方向都必須單獨進行關閉。這個原則是當一方完成它的資料發送任務後就能發送一個FIN來終止這個方向的串連。收到一個FIN只意味著這一方向上沒有資料流動,一個TCP串連在收到一個FIN後仍能發送資料。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉

第一次分手:主機1(可以使用戶端,也可以是伺服器端),設定Sequence Number和Acknowledgment Number,向主機2發送一個FIN報文段;此時,主機1進入FIN_WAIT_1狀態;這表示主機1沒有資料要發送給主機2了;

第二次分手:主機2收到了主機1發送的FIN報文段,向主機1回一個ACK報文段,Acknowledgment Number為Sequence Number加1;主機1進入FIN_WAIT_2狀態;主機2告訴主機1,我也沒有資料要發送了,可以進行關閉串連了;

第三次分手:主機2向主機1發送FIN報文段,請求關閉串連,同時主機2進入CLOSE_WAIT狀態;

第四次分手:主機1收到主機2發送的FIN報文段,向主機2發送ACK報文段,然後主機1進入TIME_WAIT狀態;主機2收到主機1的ACK報文段以後,就關閉串連;此時,主機1等待2MSL後依然沒有收到回複,則證明Server端已正常關閉,那好,主機1也可以關閉串連了。

至此,TCP的四次分手就這麼愉快的完成了

4、為什麼要三向交握
  • LISTEN: 這個也是非常容易理解的一個狀態,表示伺服器端的某個SOCKET處於監聽狀態,可以接受串連了。 
  • SYN_SENT: 當用戶端SOCKET執行CONNECT串連時,它首先發送SYN報文,因此也隨即它會進入到了SYN_SENT狀態,並等待服務端的發送三向交握中的第2個報文。SYN_SENT狀態表示用戶端已發送SYN報文。(發送端)
  • SYN_RCVD: 這個狀態與SYN_SENT遙想呼應這個狀態表示接受到了SYN報文,在正常情況下,這個狀態是伺服器端的SOCKET在建立TCP串連時的三向交握會話過程中的一個中間狀態,很短暫,基本上用netstat你是很難看到這種狀態的,除非你特意寫了一個用戶端測試程式,故意將三次TCP握手過程中最後一個 ACK報文不予發送。因此這種狀態時,當收到用戶端的ACK報文後,它會進入到ESTABLISHED狀態。(伺服器端)
  • ESTABLISHED:這個容易理解了,表示串連已經建立了。

既然總結了TCP的三向交握,那為什麼非要三次呢?怎麼覺得兩次就可以完成了。那TCP為什麼非要進行三次串連呢?在謝希仁的《電腦網路》中是這樣說的:

為了防止已失效的串連請求報文段突然又傳送到了服務端,因而產生錯誤。

在書中同時舉了一個例子,如下:

“已失效的串連請求報文段”的產生在這樣一種情況下:client發出的第一個串連請求報文段並沒有丟失,而是在某個網路結點長時間的滯留了,以致延誤到串連釋放以後的某個時間才到達server。本來這是一個早已失效的報文段。但server收到此失效的串連請求報文段後,就誤認為是client再次發出的一個新的串連請求。於是就向client發出確認報文段,同意建立串連。假設不採用“三向交握”,那麼只要server發出確認,新的串連就建立了。由於現在client並沒有發出建立串連的請求,因此不會理睬server的確認,也不會向server發送資料。但server卻以為新的運輸串連已經建立,並一直等待client發來資料。這樣,server的很多資源就白白浪費掉了。採用“三向交握”的辦法可以防止上述現象發生。例如剛才那種情況,client不會向server的確認發出確認。server由於收不到確認,就知道client並沒有要求建立串連。”

這就很明白了,防止了伺服器端的一直等待而浪費資源。

5、為什麼要四次分手

TCP協議是一種連線導向的、可靠的、基於位元組流的運輸層通訊協定,是全雙工系統模式,因此每個方向都必須單獨進行關閉。這個原則是當一方完成它的資料發送任務後就能發送一個FIN來終止這個方向的串連。收到一個FIN只意味著這一方向上沒有資料流動,一個TCP串連在收到一個FIN後仍能發送資料。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉

當主機1發出FIN報文段時,只是表示主機1已經沒有資料要發送了,主機1告訴主機2,它的資料已經全部發送完畢了;但是,這個時候主機1還是可以接受來自主機2的資料;當主機2返回ACK報文段時,表示它已經知道主機1沒有資料發送了,但是主機2還是可以發送資料到主機1的;當主機2也發送了FIN報文段時,這個時候就表示主機2也沒有資料要發送了,就會告訴主機1,我也沒有資料要發送了,之後彼此就會愉快的中斷這次TCP串連。如果要正確的理解四次分手的原理,就需要瞭解四次分手過程中的狀態變化。

  • FIN_WAIT_1: 這個狀態要好好解釋一下,其實FIN_WAIT_1和FIN_WAIT_2狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉串連,向對方發送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態。而當對方回應ACK報文後,則進入到FIN_WAIT_2狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態一般是比較難見到的,而FIN_WAIT_2狀態還有時常常可以用netstat看到。(主動方)
  • FIN_WAIT_2:上面已經詳細解釋了這種狀態,實際上FIN_WAIT_2狀態下的SOCKET,表示半串連,也即有一方要求close串連,但另外還告訴對方,我暫時還有點資料需要傳送給你(ACK資訊),稍後再關閉串連。(主動方)
  • CLOSE_WAIT:這種狀態的含義其實是表示在等待關閉。怎麼理解呢?當對方close一個SOCKET後發送FIN報文給自己,你系統毫無疑問地會回應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態。接下來呢,實際上你真正需要考慮的事情是察看你是否還有資料發送給對方,如果沒有的話,那麼你也就可以 close這個SOCKET,發送FIN報文給對方,也即關閉串連。所以你在CLOSE_WAIT狀態下,需要完成的事情是等待你去關閉串連。(被動方)
  • LAST_ACK: 這個狀態還是比較容易好理解的,它是被動關閉一方在發送FIN報文後,最後等待對方的ACK報文。當收到ACK報文後,也即可以進入到CLOSED可用狀態了。(被動方)
  • TIME_WAIT: 表示收到了對方的FIN報文,並發送出了ACK報文,就等2MSL後即可回到CLOSED可用狀態了。如果FINWAIT1狀態下,收到了對方同時帶FIN標誌和ACK標誌的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。(主動方)
  • CLOSED: 表示串連中斷。
6、為什麼採用3次握手而不是2次握手

如果兩次握手的話,用戶端有可能因為網路阻塞等原因會發送多個請求報文,這時伺服器就會建立串連,浪費掉許多伺服器的資源.

7、為什麼建立串連是三向交握,而關閉串連卻是四次揮手呢

這是因為服務端在LISTEN狀態下,收到建立串連請求的SYN報文後,把ACK和SYN放在一個報文裡發送給用戶端。而關閉串連時,當收到對方的FIN報文時,僅僅表示對方不再發送資料了但是還能接收資料,己方也未必全部資料都發送給對方了,所以己方可以立即close,也可以發送一些資料給對方後,再發送FIN報文給對方來表示同意現在關閉串連,因此,己方ACK和FIN一般都會分開發送。

8、為什麼在四次揮手中必須等待2MSL的時間什麼是2MSL

MSL是Maximum Segment Lifetime,譯為“報文最大存留時間”,他是任何報文在網路上存在的最長時間,超過這個時間報文將被丟棄。

2MSL即兩倍的MSL,TCP的TIME_WAIT狀態也稱為2MSL等待狀態,當TCP的一端發起主動關閉,在發出最後一個ACK包後,即第3次握手完成後發送了第四次握手的ACK包後就進入了TIME_WAIT狀態,必須在此狀態上停留兩倍的MSL時間。(RFC 793中規定MSL為2分鐘,實際應用中常用的是30秒,1分鐘和2分鐘等)

 

等待2MSL時間主要目的是怕最後一個ACK包對方沒收到,那麼對方在逾時後將重發第三向交握的FIN包,主動關閉端接到重發的FIN包後可以再發一個ACK應答包。在TIME_WAIT狀態時兩端的連接埠不能使用,要等到2MSL時間結束才可繼續使用。當串連處於2MSL等待階段時任何遲到的報文段都將被丟棄。不過在實際應用中可以通過設定SO_REUSEADDR選項達到不必等待2MSL時間結束再使用此連接埠。


存留時間:TCP報文(segment)是IP資料報(datagram)的資料部分,而IP頭中有一個TTL域,TTL是time to live的縮寫,中文可以譯為“存留時間”,這個存留時間是由源主機設定初始值但不是存的具體時間,而是儲存了一個IP資料報可以經過的最大路由數,每經過一個處理他的路由器此值就減1,當此值為0則資料報將被丟棄,同時發送ICMP報文通知源主機。

TTL與MSL是有關係的但不是簡單的相等的關係,MSL要大於等於TTL。

為什麼TIME_WAIT狀態需要保持2MSL這麼長的時間

如果TIME_WAIT狀態保持時間不足夠長,第一個串連就正常終止了。第二個擁有相同五元組的串連出現,而第一個串連的重複報文到達,幹擾了第二個串連。TCP事先必須防止某個串連的重複報文在串連終止後出現,所以讓TIME_WAIT狀態保持時間足夠長(2MSL),串連相應方向的上的TCP報文要麼完全響應完畢,要麼被丟棄。建立第二個串連的時候,不會混淆。

9、TIME_WAIT產生原因

a)nginx使用了短串連方式,可能會造成大量處於TIME_WAIT狀態的串連

b)TCP/IP設計者本來是這麼設計的,防止上一次串連中的包,迷路後重新出現,影響新串連(經過2MSL,上一次串連中所有的重複包都會消失);可靠的關閉TCP串連主動關閉方發送的最後一個 ack(fin) ,有可能丟失,這時被動方會重新發fin, 如果這時主動方處於CLOSED 狀態,就會響應rst 而不是ack。所以主動方要處於 TIME_WAIT 狀態,而不能是CLOSED

c)過多TIME_WAIT的解決方案

net.ipv4.tcp_syncookies = 1 //表示開啟SYN Cookies。當出現SYN等待隊列溢出時,啟用cookies來處理,可防範少量SYN攻擊,預設為0,表示關閉;net.ipv4.tcp_tw_reuse = 1 //表示開啟重用。允許將TIME-WAIT sockets重新用於新的TCP串連,預設為0,表示關閉;net.ipv4.tcp_tw_recycle = 1 //表示開啟TCP串連中TIME-WAIT sockets的快速回收,預設為0,表示關閉。net.ipv4.tcp_fin_timeout = 30 //表示如果通訊端由本端要求關閉,這個參數決定了它保持在FIN-WAIT-2狀態的時間。net.ipv4.tcp_keepalive_time = 1200 //表示當keepalive起用的時候,TCP發送keepalive訊息的頻度。預設是2小時,改為20分鐘。net.ipv4.ip_local_port_range = 1024 65000 //表示用於向外串連的連接埠範圍。預設情況下很小:32768到61000,改為1024到65000。net.ipv4.tcp_max_syn_backlog = 8192 //表示SYN隊列的長度,預設為1024,加大隊列長度為8192,可以容納更多等待串連的網路連接數。net.ipv4.tcp_max_tw_buckets = 5000 //表示系統同時保持TIME_WAIT通訊端的最大數量,如果超過這個數字,TIME_WAIT通訊端將立刻被清除並列印警告資訊,預設為180000,改為5000。

對於Apache、Nginx等伺服器,上幾行的參數可以很好地減少TIME_WAIT通訊端數量,但是對於Squid,效果卻不大。此項參數可以控制TIME_WAIT通訊端的最大數量,避免Squid伺服器被大量的TIME_WAIT通訊端拖死。

 

參考文章

http://www.cnblogs.com/tankxiao/archive/2012/10/10/2711777.html

http://blog.csdn.net/whuslei/article/details/6667471

http://molewan.blog.51cto.com/287340/114592

http://www.jellythink.com/archives/705

https://wiki.wireshark.org/DisplayFilters

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.