1.三次握手詳解
三次握手(three-way handshake)是指客戶端與伺服器一共傳送三個包來建立tcp連線,三次握手的主要作用是為了確認雙方的接受能力和傳送能力是否正常,並同步序列號,保證傳輸的可靠性。
剛開始客戶端和伺服器均處於 closed 狀態,在socket程式設計中,伺服器 listen() 之後被動開啟,客戶端 connection() 之後主動開啟,之後進行三次握手:
分析方式(報文型別,編號,所處狀態)
第一次握手:客戶端給伺服器傳送syn報文,並指明客戶端的isn,此時客戶端處於syn-sent狀態。
tcp報文頭部 syn = 1 , seq = x, syn報文會消耗序列號,不能夠攜帶資料。
第二次握手:伺服器收到了客戶端的syn報文之後,會傳送自己的syn-ack報文作為應答,在報文中指明了自己的isn;並將客戶端的 isn + 1 作為ack值,傳送給客戶端,表示自己已經收到了客戶端的syn,此時伺服器處於syn-rcvd 狀態。
tcp報文頭部 syn = 1, ack = 1,seq = y, ack = x + 1,syn報文會消耗序列號,不能攜帶資料。
第三次握手:客戶端接收到伺服器的syn之後,傳送ack報文作為應答,將伺服器的 isn+1 作為 ack 的值,表示自己已經收到了伺服器的syn報文,傳送後客戶端進入 established 狀態,伺服器收到ack後也進入 established 狀態,雙方開始資料交換。
tcp報文頭部 ack = 1, seq = x + 1,ack = y + 1, ack報文如果攜帶資料則會消耗序列號,如果不攜帶資料則不會消耗序列號。
為什麼要三次握手?只有兩次握手可以嗎?
三次握手才能保證雙方的接收傳送能力都是正常的,第三次握手有兩點作用:
1.客戶端的syn報文因網路延時後滯後,此時客戶端超時重傳syn報文並與伺服器已經完成了資料的傳輸,隨後第一次的syn報文之後到達伺服器,伺服器誤認為這是一次新的連線請求,於是傳送syn-ack給客戶端,但是客戶端會直接忽略這一次syn-ack,導致伺服器空等待。
2.如果第二次握手的ack訊號丟失,伺服器直接進入established狀態,而客戶端沒有收到,會形成伺服器空等待。
什麼是半連線佇列?什麼是全連線佇列?
在伺服器收到客戶端的syn之後,進入syn-rcvd狀態,此時雙方還沒有完全建立連線,伺服器將此狀態稱為半連線狀態,並放入半連線佇列中;全連線佇列也就是存放完成了三次握手的連線的佇列。
isn是什麼?是固定的嗎?
isn是一端為建立連線傳送syn時選擇的乙個初始序列號,isn隨時間而變化(每4ms加1),因此每乙個連線都有不同的isn。
isn不固定有兩個好處:
1.如果isn固定,上一次連線的報文因網路延遲在這一次連線中到達,並恰好兩次的seq相同,那麼就會發生網路混亂。
2.固定isn容易遭受到黑客攻擊,黑客能得知伺服器的isn,能在第三次握手正確的返回ack報文,與伺服器建立連線。
三次握手過程中可以攜帶資料嗎?
第一次第二次握手不行,第三次握手可以;
假如第一次握手可以攜帶資料,那麼如果有人要惡意攻擊伺服器,會在syn報文中存入大量資料,並瘋狂傳送syn報文,伺服器將會因處理這些報文陷入癱瘓。
第三次握手返回ack報文時,雙方連線已經建立,自然可以攜帶資料。
syn攻擊是什麼?syn泛洪攻擊是什麼?
client偽造大量不存在的ip位址,並不斷向server傳送syn請求,由於ip位址不存在,server會不斷傳送syn-ack報文直至超時,這些偽造的syn報文將導致半連線佇列滿,導致正常的syn請求因無法加入半連線佇列而被丟棄,這樣會造成伺服器癱瘓。
常見的防禦syn攻擊的方法有:
1.過濾網關防護
如設定syn**,讓**為伺服器處理syn請求,如果收到了客戶端的ack包那麼就向伺服器完成三次握手。
2.增大半連線佇列容量
3.縮短超時時間與減少重傳次數
4.syncookies技術
如果已經建立了連線,但是客戶端突然出現故障了怎麼辦?
服務端會有乙個超時關閉機制,如果限定時間內沒有接收到客戶端的資料傳送,那麼就認為客戶端已經出現故障, 伺服器自動斷開。
四次揮手詳解
剛開始客戶端和服務端都處於established狀態,假設客戶端先發起關閉請求:
在socket程式設計中,任意一方執行 close()操作,都會執行四次揮手。
第一次揮手:客戶端向服務端傳送fin報文,同時指定自己的序列號,此時客戶端處於 fin-wait1 狀態。
tcp報文頭部資訊:fin = 1,seq = u,fin會消耗乙個序列號,不能攜帶資料。
第二次揮手:服務端接收到客戶端的fin報文後,傳送ack報文作為應答,ack值為客戶端序列號+1,服務端處於 close-wait 狀態,客戶端收到ack後處於fin-wait2狀態,此時tcp處於半關閉狀態,服務端仍然在向客戶端傳送資料。
tcp報文頭部資訊:ack = 1,seq = v,ack = u + 1,ack報文攜帶資料則消耗序列號,不攜帶則不消耗序列號。
第三次揮手:服務端傳送完資料之後,向客戶端傳送 fin-ack報文,同時指定自己的序列號,ack的值仍然為 客戶端序列號 + 1,此時服務端處於 last-ack 狀態。
tcp報文頭部資訊:fin = 1, ack = 1,seq = w,ack = u + 1,fin報文會消耗乙個序列號,不能攜帶資料。
第四次揮手:客戶端接收到服務端的fin-ack報文後,傳送ack報文給客戶端,ack值為服務端序列號 + 1,此時客戶端處於 time-wait 狀態,需要等待 2msl,之後進入closed狀態,服務端接收到ack後也進入closed狀態。
tcp報文頭部資訊:ack = 1,seq = u + 1, ack = w + 1,ack報文攜帶資料會消耗序列號,不攜帶資料則不消耗序列號。
為什麼連線的時候是三次握手,關閉的時候卻是四次揮手?(為什麼揮手需要四次?三次揮手不行嗎?)
三次握手的時候客戶端傳送syn,伺服器可以直接返回syn-ack;但是在四次揮手中,由於tcp的半關閉性,所以伺服器收到fin後,並不能立刻返回fin-ack,而是先傳送ack,等到資料傳輸完成之後,再傳送fin-ack,這兩個不能合到一起傳送,所以需要四次揮手來關閉連線。
為什麼客戶端需要等待2msl再關閉?
原因有兩點:
1.保證客戶端最後傳送的ack能夠到達客戶端
如果這個ack報文丟失,伺服器超時重傳fin-ack,客戶端在2msl的時間內一定可以接收到這個超時重傳的fin-ack,這樣可以避免伺服器沒有收到最後的ack而空等待。
2.防止舊連線中的報文影響新連線
客戶端在傳送最後乙個ack後,等待2msl,這樣該連線中的所有報文都已經在網路中消失,不會影響到下乙個新的連線。
TCP三次握手 四次揮手詳解
1 建立連線協議 三次握手 1 客戶端傳送乙個帶syn標誌的tcp報文到伺服器。這是三次握手過程中的報文1。2 伺服器端回應客戶端的,這是三次握手中的第2個報文,這個報文同時帶ack標誌和syn標誌。因此它表示對剛才客戶端syn報文的回應 同時又標誌syn給客戶端,詢問客戶端是否準備好進行資料通訊。...
TCP三次握手 四次揮手詳解
1 建立連線協議 三次握手 1 客戶端傳送乙個帶syn標誌的tcp報文到伺服器。這是三次握手過程中的報文1。2 伺服器端回應客戶端的,這是三次握手中的第2個報文,這個報文同時帶ack標誌和syn標誌。因此它表示對剛才客戶端syn報文的回應 同時又標誌syn給客戶端,詢問客戶端是否準備好進行資料通訊。...
TCP三次握手 四次揮手詳解
1 建立連線協議 三次握手 1 客戶端傳送乙個帶syn標誌的tcp報文到伺服器。這是三次握手過程中的報文1。2 伺服器端回應客戶端的,這是三次握手中的第2個報文,這個報文同時帶ack標誌和syn標誌。因此它表示對剛才客戶端syn報文的回應 同時又標誌syn給客戶端,詢問客戶端是否準備好進行資料通訊。...