TCP詳解(2):三次握手與四次揮手

  TCP(Transmission Control Protocol,傳輸控制協議)是基於連接的協議,也就是說,在正式收發數據前,必須和對方建立可靠的連接,就好像你給別人打電話,必須等線路接通了、對方拿起話筒建立了連接才能相互通話。
  一個TCP連接必須要經過三次“對話”才能建立起來,其中的過程非常複雜,我們這裏只做簡單、形象的介紹,你只要做到能夠理解這個過程即可。我們來看看這三次對話的簡單過程:主機A向主機B發出連接請求數據包:“我想給你發數據,可以嗎?”,這是第一次對話;主機B向主機A發送同意連接和要求同步(同步就是兩臺主機一個在發送,一個在接收,協調工作)的數據包:“可以,你什麼時候發?”,這是第二次對話;主機A再發出一個數據包確認主機B的要求同步:“我現在就發,你接着吧!”,這是第三次對話。三次“對話”的目的是使數據包的發送和接收同步,經過三次“對話”之後,主機A才向主機B正式發送數據。

   

1. 建立連接三次握手
  TCP用三次握手(three-way handshake)過程創建一個連接。在連接創建過程中,很多參數要被初始化,例如序號被初始化以保證按序傳輸和連接的強壯性。
  一對終端同時初始化一個它們之間的連接是可能的。但通常是由一端打開一個套接字(socket)然後監聽來自另一方的連接,這就是通常所指的被動打開(passive open)。服務器端被被動打開以後,用戶端就能開始創建主動打開(active open)。
  1)客戶端通過向服務器端發送一個SYN來創建一個主動打開,作爲三路握手的一部分。客戶端把這段連接的序號設定爲隨機數 A。
  2)服務器端應當爲一個合法的SYN回送一個SYN/ACK。ACK 的確認碼應爲 A+1,SYN/ACK 包本身又有一個隨機序號 B。
  3)最後,客戶端再發送一個ACK。當服務端受到這個ACK的時候,就完成了三路握手,並進入了連接創建狀態。此時包序號被設定爲收到的確認號 A+1,而響應則爲 B+1。
   

  Win:窗口字段明確指出現在允許對方發送的數據量(經常變化)
  Len:TCP數據段長度
  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,如果服務器MSS=1460,而客戶端的MSS=1440,最終爲1440。

  在TCP的三次握手中,不僅是建立了連接,還讓雙方交換了有效信息,過程如下:
  1) 嗨~ , 這是我sequence number和MSS
  2) 我收到啦~, 這是我sequence number和MSS
  3) 我也收到~

爲什麼需要三次握手?
  簡單地說,就是要保證在一段有效時間內,雙方收到對方的有效信息。
  一個簡單例子,A發給B,B回覆A,如果A不再回復B,B如何知道A收到了自己的信息?
  謝希仁版《計算機網絡》中的例子是這樣的,“已失效的連接請求報文段”的產生在這樣一種情況下:client發出的第一個連接請求報文段並沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以後的某個時間纔到達server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段後,就誤認爲是client再次發出的一個新的連接請求。於是就向client發出確認報文段,同意建立連接。假設不採用“三次握手”,那麼只要server發出確認,新的連接就建立了。由於現在client並沒有發出建立連接的請求,因此不會理睬server的確認,也不會向server發送數據。但server卻以爲新的運輸連接已經建立,並一直等待client發來數據。這樣,server的很多資源就白白浪費掉了。採用“三次握手”的辦法可以防止上述現象發生。例如剛纔那種情況,client不會向server的確認發出確認。server由於收不到確認,就知道client並沒有要求建立連接。”。
  不管哪個例子,都是爲了滿足”在不可靠信道上可靠地傳輸信息”這一需求。請注意這裏的本質需求,信道不可靠,數據傳輸要可靠。還是那句話,就是要保證在一段有效時間內,雙方收到對方的有效信息。

SYN攻擊
  在三次握手過程中,服務器發送SYN-ACK之後,收到客戶端的ACK之前的TCP連接稱爲半連接(half-open connect).此時服務器處於Syn_RECV狀態.當收到ACK後,服務器轉入ESTABLISHED狀態.
SYN攻擊就是攻擊客戶端在短時間內僞造大量不存在的IP地址,向服務器不斷地發送syn包,服務器回覆確認包,並等待客戶的確認,由於源地址是不存在的,服務器需要不斷的重發直 至超時,這些僞造的SYN包將長時間佔用未連接隊列,正常的SYN請求被丟棄,目標系統運行緩慢,嚴重者引起網絡堵塞甚至系統癱瘓。
  SYN攻擊是一個典型的DDOS攻擊。檢測SYN攻擊非常的方便,當你在服務器上看到大量的半連接狀態時,特別是源IP地址是隨機的,基本上可以斷定這是一次SYN攻擊.在Linux下可以如下命令檢測是否被Syn攻擊:
netstat -n -p TCP | grep SYN_RECV
  一般較新的TCP/IP協議棧都對這一過程進行修正來防範SYN攻擊,修改TCP協議實現。主要方法有SynAttackProtect保護機制、SYN cookies技術、增加最大半連接和縮短超時時間等.
  但是不能完全防範SYN攻擊。

Socket狀態對應
  Socket API 和 TCP 協議中各個狀態是如何對應的呢?我們可以通過下圖來看:

  

2. 斷開連接四次揮手
  由於TCP連接是全雙工的,因此每個方向都必須單獨進行關閉。這個原則是當一方完成它的數據發送任務後就能發送一個FIN來終止這個方向的連接。比如服務器收到一個FIN只意味着客戶端不再發送數據,但它還可以向客戶端發送數據,當服務器不再發數據了,他也要向客戶端發送FIN。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。
  
    

四次揮手過程如下:
  1)客戶端A發送一個FIN,用來關閉客戶A到服務器B的數據傳送。
  2)服務器B收到這個FIN,它發回一個ACK,確認序號爲收到的序號加1。和SYN一樣,一個FIN將佔用一個序號。
  3)服務器B關閉與客戶端A的連接,發送一個FIN給客戶端A。
  4)客戶端A發回ACK報文確認,並將確認序號設置爲收到序號加1。

狀態變化

  

  FIN_WAIT_1: 當SOCKET在ESTABLISHED狀態,主動關閉連接時,向對方發送FIN報文,此時該SOCKET進入到FIN_WAIT_1狀態。當對方迴應ACK報文後,則進入到FIN_WAIT_2狀態。(主動方)
  FIN_WAIT_2:處於FIN_WAIT_2狀態下的SOCKET爲半連接狀態,等待對方發起斷開要求,(注意對方可以在斷開時捎帶信息)稍後再關閉連接。(主動方)
  TIME_WAIT: 收到了對方FIN報文,併發送出了ACK報文,等待2MSL後即可回到CLOSED狀態了。
  注意:在FIN_WAIT_1狀態下,如果收到了對方同時帶FIN和ACK標誌的報文(複用一個報文)時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。(主動方)
  CLOSING(比較少見): 如果雙方几乎同時試圖斷開一個SOCKET的話,那麼就出現了雙方同時發送FIN報文的情況,即會出現CLOSING狀態,表示雙方都試圖關閉SOCKET連接。
  CLOSE_WAIT: 等待關閉連接,當對方發送FIN報文,迴應ACK報文給對方後,則進入到CLOSE_WAIT狀態。如果此時沒有數據發送給對方,就可以關閉這個SOCKET,發送FIN報文給對方,即關閉連接。(被動方)
  LAST_ACK: 被動關閉方在發送FIN報文後,最後等待對方的ACK報文。當收到ACK報文後,進入到CLOSED狀態。(被動方)
  CLOSED: 連接中斷。

Socket狀態變化
  
    

參考:
https://zh.wikipedia.org/wiki/%E4%BC%A0%E8%BE%93%E6%8E%A7%E5%88%B6%E5%8D%8F%E8%AE%AE
http://www.kuqin.com/shuoit/20141018/342719.html
http://hackerxu.com/2014/11/16/TCP.html
https://www.centos.bz/2012/08/tcp-establish-close/
http://blog.csdn.net/xifeijian/article/details/12777187
http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html
http://blog.163.com/xychenbaihu@yeah/blog/static/13222965520118139252103/
https://commons.wikimedia.org/wiki/File:Tcp_close.svg

發佈了89 篇原創文章 · 獲贊 9 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章