-
1 # 三旺通訊
-
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等,來擾亂連線。
回覆列表
一、三次握手
三次握手:在通訊之前,會先透過三次握手的機制來確認兩埠之間的連線是否可用。而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的標誌,所以四次揮手是不能夠改變的。