首頁>Club>
CP作為一種可靠傳輸控制協議,其核心思想:既要保證資料可靠傳輸,又要提高傳輸的效率,而用三次恰恰可以滿足以上兩方面的需求~
12
回覆列表
  • 1 # 三旺通訊

    一、三次握手

    三次握手:在通訊之前,會先透過三次握手的機制來確認兩埠之間的連線是否可用。而UDP不需要確認是否可用,直接傳。

    三次握手機制

    一開始客戶端和服務端都是關閉狀態,但是在某個時刻,客戶端需要和服務端進行通訊,此時雙方都會各自準備好埠,伺服器段的埠會處於監聽狀態,等待客戶端的連線。

    客戶端可會知道自己的埠號,和目的程序的埠號,這樣才能發起請求。

    第一次握手:客戶端想與伺服器進行連線了,所以狀態變為主動開啟,同時傳送一個連線請求報文給伺服器段SYN=1,並且會攜帶x個位元組過去。

    傳送完請求連線報文後,客戶端的狀態就變為了SYN_SENT,可以說這個狀態是等待發送確認(為了傳送第三次握手時的確認包)

    第二次握手:服務端接收到連線請求報文後,從LSTTEN狀態變為被動開啟狀態,然後給客戶端返回一個報文。這個報文有兩層意思,一是確認報文,而可以達到告訴客戶端,我也開啟連線了。

    發完後,變為SYN_RCVD狀態(也可以說是等待接受確認狀態,接受客戶端發過來的確認包)

    第三次握手:客戶端得到伺服器端的確認和知道伺服器端也已經準備好了連線後,還會發一個確認報文到伺服器端,告訴伺服器端,我接到了你傳送的報文,接下來就讓我們兩個進行連線了。

    客戶端傳送完確認報文後,進入ESTABLISHED,而伺服器接到了,也變為ESTABLISHED

    進入到ESTABLISHED狀態後,連線就已經完成了,可以進行通訊了。

    問題:為什麼需要第三次握手,有前面兩次不就已經可以了嗎?

    假設沒有第三次握手,客戶端傳送一個連線請求報文過去,但是因為網路延遲,在等待了一個超時時間後,客戶端就會再重新發一個請求連線報文過去,然後正常的進行;

    伺服器端發回一個確認連線報文,然後就開始通訊,通訊結束後,那個第一次因為網路延遲的請求連線報文到了伺服器端,伺服器端不知道這個報文已經失效,也發回了一個確認連線報文。

    客戶端接收後,發現自己並沒有傳送連線請求(因為超時了,所以就認為自己沒有發),所以對這個確認連線請求就什麼也不做,但是此時客戶端不這麼認為,他認為連線已經建立了,就一直開啟著等待客戶端傳資料過來,這就造成了極大的浪費。

    如果有了第三次握手,那麼客戶端就可以通知伺服器了,所以第三次握手也很重要!

    二、四次揮手

    四次揮手是用來斷開伺服器和客戶端之間的通訊的,之所以要斷開連線,是因為TCP/IP 協議是要佔用埠號的,而計算機的埠卻是有限的,不進行斷開的話,勢必會造成計算機資源的浪費。

    1、在整個通訊的過程中,誰先發起請求,誰就是客戶端。

    當客戶端的資料傳輸到尾部時,客戶端向伺服器傳送帶有FIN標誌的資料包,使其明白自己準備斷開通訊了。

    2、因為TCP的通訊是使用全雙工通訊的WebSocket,所以在斷開連線的時候也應該是雙向的;當伺服器收到帶有FIN標誌的資料包時,其必不會直接傳送FIN標誌斷開通訊的請求,而是先發送一個帶有ACK標誌的應答資訊,使客戶端明白伺服器還有資料要進行傳送。

    3、當 伺服器的資料傳送完成後,向客戶端傳送帶有FIN標誌的資料包,通知客戶端斷開連線。

    4、這一次揮手是我覺得四次揮手中設計的最巧妙的一次。

    當客戶端收到FIN後,擔心網路上某些不可控制的因素導致伺服器不知道他要斷開連線,會發送ACK進行確認,同時把自己設定成TIME_WAIT狀態並啟動定時器,**在TCP的定時器到達後客戶端並沒有接收到請求,會重新發送;當伺服器收到請求後就斷開連線;當客戶端等待2MLS(兩倍報文最大生存時間)後,沒有收到請求重傳的請求後,客戶端這邊就斷開連線,**整個TCP通訊就結束了。

    四次揮手的圖如下所示:

    問題:關閉的時候為什麼會是四次揮手?

    四次揮手不能像三次握手一樣,三次握手可以將ACK+SYN 一起傳送,ACK用於確認資訊,SYN卻是用來建立聯機的;

    四次揮手中ACK是不能和FIN一起傳送,ACK只是告訴客戶端確認我收到了,等我將資料傳送完畢之後會向其傳送FIN的標誌,所以四次揮手是不能夠改變的。

  • 2 # 阿旭的世界

    第一次握手:客戶端傳送TCP包,置SYN標誌位為1,將初始序號X,儲存在包頭的序列號(Seq)裡。

    第二次握手:服務端迴應確認包,置SYN標誌位為1,置ACK為X+1,將初始序列號Y,儲存在包頭的序列號裡。

    第三次握手:客戶端對服務端的確認包進行確認,置SYN標誌位為0,置ACK為Y+1,置序列號為Z。

    為什麼不是兩次

    重新看一遍圖(S-服務端,C-客戶端)

    第一次握手後,S可以確認自己收報文與C發報文的功能都正常,而C呢,它什麼都不能確認。

    第二次握手後,C可以確認自己的收發報文與S的收發報文功能都正常,也就是認為連線已建立。

    那麼第三次呢,S也可以確認雙方能夠正常通訊。

    假想一下,如果我們去掉了第三次呢?

    如果只是第二次建立的話,服務端和客戶端就已經建立,但是如果客戶端沒有收到服務端的迴應?這個時候,客戶端認為沒有建立,服務端卻為認為建立成功,並儲存了必要的資源,如果出現大量的這樣的情況。那麼伺服器會奔潰。

    因此第三次握手是必要的。

    為什麼不是四次

    因為三次握手後,C和S至少可以確認之前的通訊情況,但無法確認之後的情況。 所以如果四次還是五次或是更多次都是徒勞的

  • 3 # 石墨烯大傅

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

    TCP是傳輸控制協議。

    syn是該協議中的一個標誌位。如果該位被置為1,則表示這個報文是一個請求建立連線的報文。ack也是該協議的一個標誌位。如果該位被置為1,則表示這個報文是一個用於確認的報文。

    seq是序列號,這是為了連線以後傳送資料用的,ack是對收到的資料包的確認,值是等待接收的資料包的序列號。在第一次訊息傳送中,A隨機選取一個序列號x作為自己的初始序號傳送給B;第二次訊息B使用ack對A的資料包進行確認,因為已經收到了序列號為x的資料包,準備接收A序列號為x+1的包,所以ack=x+1,同時B告訴A自己的初始序列號,就是seq=y;第三條訊息A告訴B收到了B的確認訊息並準備建立連線,A自己此條訊息的序列號是x+1,所以seq=x+1,而ack=y+1是表示A正準備接收B序列號為y+1的資料包。seq是資料包本身的序列號;ack是期望對方繼續傳送的那個資料包的序列號。

    (1)第一次握手:Client將標誌位SYN((同步序列編號(Synchronize Sequence Numbers))置為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攻擊:在三次握手過程中,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

  • 4 # O0o0o0o0O

    你聽到了嗎?

    聽到了,你呢?

    我也聽到了

    三次之後確保雙方能通訊,少哪句都是不通的

  • 5 # 子闕創客

    為了實現可靠資料傳輸, TCP 協議的通訊雙方, 都必須維護一個序列號, 以標識傳送出去的資料包中, 哪些是已經被對方收到的。 三次握手的過程即是通訊雙方相互告知序列號起始值, 並確認對方已經收到了序列號起始值的必經步驟。

    如果只是兩次握手, 至多隻有連線發起方的起始序列號能被確認, 另一方選擇的序列號則得不到確認

    以下圖1是正確握手,圖2、3是如果是2次示例

  • 6 # 一個程式設計師的奮鬥史

    下面言歸正傳,對題主的問題進行回答。首先我們需要明白到底什麼是三次握手!

    什麼是三次握手?

    下面的過程來自維基百科的解釋:

    客戶端透過向伺服器端傳送一個SYN來建立一個主動開啟,作為三次握手的一部分。客戶端把這段連線的序號設定為隨機數A。

    伺服器端應當為一個合法的SYN回送一個SYN/ACK。ACK的確認碼應為A+1,SYN/ACK包本身又有一個隨機產生的序號B。

    最後,客戶端再發送一個ACK。此時包的序號被設定為A+1,而ACK的確認碼則為B+1。當服務端收到這個ACK的時就完成了三次握手,並進入了連線建立狀態。

    為什麼是三次,而不是二次或者四次?

    還記得我們初中數學常用的反證法嗎?在這裡同樣適用。

    0x01. 假設TCP連線過程採用「四次握手」,我們來模擬下其過程:

    A 傳送同步訊號SYN + A"sInitial sequence number

    B 確認收到A的同步訊號,並記錄A"s ISN 到本地,命名 B"s ACK sequence number

    B傳送同步訊號SYN + B"s Initial sequence number

    A確認收到B的同步訊號,並記錄B"s ISN 到本地,命名 A"s ACK sequence number

    很顯然,步驟2和步驟3重複了,可以合併,只需三次握手即可完成,否則會造成網路資源的浪費。

    0x02. 假設TCP連線過程採用「二次握手」,模擬過程如下:

    A 傳送同步訊號SYN + A"sInitial sequence number

    B傳送同步訊號SYN + B"sInitial sequence number + B"s ACK sequence number

    看出問題了吧,A的初始序列號在A、B之間達成了一致,但是B無法知道A是否已經接收到自己的同步訊號,如果這個同步訊號丟失了,A和B就B的初始序列號將無法達成一致。

    所以,TCP的設計者才選用了三次握手機制。

  • 7 # ToBeGeek

    實名反對類比的方法來解釋,雖然簡單,但也錯誤,沒有回答本質問題

    先總結一下:

    為什麼不能2次握手,因為2次無法處理過期的資料包4次或以上行嗎,可以但沒必要,我們追求的當然是最少需要幾步,其實現在的三次握手就是四次,只是中間的的SYN和ACK合併為了一個(SYN,ACK)

    一、什麼是建立連線

    首先要明確的是什麼是“建立連線”, 在RFC798中明確指出了連線是什麼:

    簡而言之,連線並不是一根電話線,而是一組資訊,包括(Sockets、序列號、視窗大小),他們用來實現傳輸可靠性和資料流控制機制

    其中

    Socket表現在資料包中其實就是埠號,IP地址在IP資料包頭部中,雙方同步了IP+端口才能通訊;序列號用來標識資料包的順序,這樣才能實現重傳機制,接收方才能正確組裝資料;視窗大小用於流量控制,不再展開;

    所以建立連線,就是通訊雙方同步(Sockets、序列號、視窗大小)資訊的過程。

    二、兩次握手行不行

    這點在RFC798中其實也有體現,如果網路較差,A傳送SYN給B後,遲遲沒有回覆,再次傳送了一個SYN,這時B對第一個SYN的ACK姍姍來遲,如果沒有第三次A對B的ACK,那麼B就進入連線狀態,但是此時A已經放棄了此連線,B的資源就被白白浪費了。

    因此必須要有第三次握手,並且加入RST資料包,用來告知對方停止此連線,每當通訊一方收到的ACK對應的是已過期SYN,就會發送一個RST來通知對方。

    三、為什麼序列號都是隨機的

    這裡再擴充套件一下,為什麼雙方的序列號要從隨機數字開始+1,因為資料包的源IP和埠都是可以偽造的,如果序列號從一個常數比如0開始,A和B正在通訊,C很容易就可以偽造一個A的資料包,來給B傳送一個RST等,來擾亂連線。

  • 中秋節和大豐收的關聯?
  • 銀行錯轉到卡上一億,馬上用它去做生意賺了一筆然後,還1億給銀行違法嗎?