寫到最後發現我描述的挺水的,這個老哥的用語比較專業一點 (老哥這篇有些許錯別字
大家可以看看它的. 看我的這篇可能會比較好理解一點,畢竟都是大白話
三次握手!
三次握手其實不準確。在官方文件中對於tcp連線,是用握手 handshake 來描述整個tcp連線 建立的過程。
只握一次手就可以建立tcp連線。那麼為什麼說是三次握手建立連線呢? 其實它的三次是傳送 三個報文,我們可以說是三報文握手
①一開始客戶機和伺服器都處於關閉狀態,客戶機主動開啟,向伺服器傳送乙個報文。這個報文攜帶著 syn = 1 (同步)和seq = x (乙個序列號,有各自的序列號,會不斷的增加)
此時客戶端處於 :syn-sent狀態
ps:大概看一下
同步syn:連線建立時用於同步序號。當syn=1,ack=0時表示:這是乙個連線請求報文段。若同意連線,則在響應報文段中使得syn=1,ack=1。因此,syn=1表示這是乙個連線請求,或連線接受報文。syn這個標誌位只有在tcp建產連線時才會被置1,握手完成後syn標誌位被置0。
序列號seq:佔4個位元組,用來標記資料段的順序,tcp把連線中傳送的所有資料位元組都編上乙個序號,第乙個位元組的編號由本地隨機產生;給位元組編上序號後,就給每乙個報文段指派乙個序號;序列號seq就是這個報文段中的第乙個位元組的資料編號。
② 然後我們的伺服器就 被動開啟,處於監聽狀態,等待客戶機傳送第乙個握手的報文。
收到客戶機傳送的報文後,就會立刻向客戶機傳送乙個確認報文---------------
ack =1 ,syn = 1,seq = y, (小寫)ack = x + 1
(大寫)ack是確認位,如果為1,**確認報文有效 .如果為0,則可以直接忽略,是沒有意義的
此時服務端處於syn-recv狀態
③這次的報文也有ack = 1,確認位有效,ack = y + 1 ,是確認報文
就是' 我 確認 我 收到了你的 確認報文 '
就是我們客戶端,確認,服務端傳送的確認報文 我們客戶端收到了
就是 伺服器端,用來確認客戶端傳送的用來建立連線的報文,我服務端收到了,那我服務端發給你客戶端的這個確認報文,你客戶端收到了沒有呢?
over 此時客戶端伺服器處於 established(tcp連線成功狀態)
細節: ①seq = x 到 ③seq = x + 1 說明客戶機在傳送③報文之前,期間是沒有再傳送其他報文
然後伺服器收到確認報文後,就建立了tcp連線
有個疑問?明明執行①②的時候,tcp連線就可以建立了,那為什麼客戶端還有再次傳送乙個確認報文過去呢?
是因為①這樣乙個請求報文,可能會在傳送途中就失效了。這個失效不是說它 沒有作用了。
而是說 由於網路中某種原因,導致這個請求報文在網路中發生了 阻塞滯留, 但是tcp連線有乙個超時重傳機制
那麼①請求報文沒有到達的話,服務端就沒有收到。收不到這一條 ,服務端就會認為剛剛的①請求報文沒有發出去,那客戶端就會再次傳送一遍請求報文。
而剛剛那條請求報文就滯留在網路中。 客戶端再次傳送一條同樣的建立tcp連線的請求,這次服務端就收到了,然後 進行②確認 ③確認,這樣就建立tcp連線了
就在我們美滋滋建立tcp連線成功,用完了連線後,就銷毀掉了
然而剛剛滯留在網路中的那條 連線,可能我們的網路突然又通暢了,那剛剛那條連線又生效了,又到達了伺服器
伺服器收到了,就會再次給客戶端傳送確認報文 。 如果沒有③這一次確認報文,那麼tcp連線就建立了。
但是這條連線 我們不需要這次建立。因為我們之前已經重新 傳了一次請求報文,建立了連線,並釋放了。
所以沒有③就會重新建立一次連線,我們不需要這次連線。
有了③之後,伺服器傳送過來的確認報文,我客戶端這邊 收到後會說:我沒有給你傳送啊。
那麼就不會處理剛剛那條 '連線'
四次揮手
關閉之前都是建立狀態
①客戶端傳送 『連線釋放報文』,頭部攜帶的 fin =1,seq = u 序列值為u 終止fin:用來釋放乙個連線。fin=1表示:此報文段的傳送方的資料已經傳送完畢,並要求釋放運輸連線
②服務端收到報文後,知道客戶端需要斷開連線。 那我給你傳送乙個確認報文,ack = 1,代表確認有效 seq 為 v , ack = u +1
客戶端收到報文, 客戶端 ---》服務端 這個方向的tcp連線已經斷開,已經失效了
而 客戶端 《--- 服務端 這個方向還是可以連線的
③ 但是我們服務端可能還要資料沒有傳遞過去,就需要重新傳送報文, fin = 1,ack = 1,seq = w, ack = u+1 細節:①的seq = v ③的seq = w 正常都是+1,v到w說明中間不連續
這次是 伺服器要斷開 對客戶端的連線
④ 伺服器端可能沒有收到我們的④確認報文, 伺服器就會認識是自己傳送的③我們沒有收到,那麼服務端就會再次傳送③,我要關閉了。這就是為啥要設定2msl 最大報文生成時段
要不然客戶端都已經關閉了,那你服務端還傳送個錘子?
客戶端收到伺服器的連線釋放報文後,必須發出確認,ack=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了time-wait(時間等待)狀態。注意此時tcp連線還沒有釋放,必須經過2msl(最長報文段壽命)的時間後,當客戶端撤銷相應的tcb後,才進入closed狀態。
【問題1】為什麼連線的時候是三次握手,關閉的時候卻是四次握手?
答:因為當server端收到client端的syn連線請求報文後,可以直接傳送syn+ack報文。其中ack報文是用來應答的,syn報文是用來同步的。但是關閉連線時,當server端收到fin報文時,很可能並不會立即關閉socket,所以只能先回覆乙個ack報文,告訴client端,"你發的fin報文我收到了"。只有等到我server端所有的報文都傳送完了,我才能傳送fin報文,因此不能一起傳送。故需要四步握手。
【問題2】為什麼time_wait狀態需要經過2msl(最大報文段生存時間)才能返回到close狀態?
答:雖然按道理,四個報文都傳送完畢,我們可以直接進入close狀態了,但是我們必須假象網路是不可靠的,有可以最後乙個ack丟失。所以time_wait狀態就是用來重發可能丟失的ack報文。在client傳送出最後的ack回覆,但該ack可能丟失。server如果沒有收到ack,將不斷重**送fin片段。所以client不能立即關閉,它必須確認server接收到了該ack。client會在傳送出ack之後進入到time_wait狀態。client會設定乙個計時器,等待2msl的時間。如果在該時間內再次收到fin,那麼client會重發ack並再次等待2msl。所謂的2msl是兩倍的msl(maximum segment lifetime)。msl指乙個片段在網路中最大的存活時間,2msl就是乙個傳送和乙個回覆所需的最大時間。如果直到2msl,client都沒有再次收到fin,那麼client推斷ack已經被成功接收,則結束tcp連線。
【問題3】為什麼不能用兩次握手進行連線?
答:3次握手完成兩個重要的功能,既要雙方做好傳送資料的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始序列號進行協商,這個序列號在握手過程中被傳送和確認。
現在把三次握手改成僅需要兩次握手,死鎖是可能發生的。作為例子,考慮計算機s和c之間的通訊,假定c給s傳送乙個連線請求分組,s收到了這個分組,併發 送了確認應答分組。按照兩次握手的協定,s認為連線已經成功地建立了,可以開始傳送資料分組。可是,c在s的應答分組在傳輸中被丟失的情況下,將不知道s 是否已準備好,不知道s建立什麼樣的序列號,c甚至懷疑s是否收到自己的連線請求分組。在這種情況下,c認為連線還未建立成功,將忽略s發來的任何資料分 組,只等待連線確認應答分組。而s在發出的分組超時後,重**送同樣的分組。這樣就形成了死鎖。
【問題4】如果已經建立了連線,但是客戶端突然出現故障了怎麼辦?
tcp還設有乙個保活計時器,顯然,客戶端如果出現故障,伺服器不能一直等下去,白白浪費資源。伺服器每收到一次客戶端的請求後都會重新復位這個計時器,時間通常是設定為2小時,若兩小時還沒有收到客戶端的任何資料,伺服器就會傳送乙個探測報文段,以後每隔75秒鐘傳送一次。若一連傳送10個探測報文仍然沒反應,伺服器就認為客戶端出了故障,接著就關閉連線
TCP建立連線三次握手和釋放連線四次握手
尊重 在談及tcp建立連線和釋放連線過程,先來簡單認識一下 tcp報文段首部格式 的的幾個名詞 這裡只是簡單說明,具體請檢視相關教程 序列號seq 佔4個位元組,用來標記資料段的 順序,tcp把連線中傳送的所有資料位元組都編上乙個序號,第乙個位元組的編號由本地隨機產生 給位元組編上序號後,就給每乙個...
TCP建立連線三次握手和釋放連線四次握手
尊重 在談及tcp建立連線和釋放連線過程,先來簡單認識一下tcp報文段首部格式 的的幾個名詞 這裡只是簡單說明,具體請檢視相關教程 序列號seq 佔4個位元組,用來標記資料段的順序,tcp把連線中傳送的所有資料位元組都編上乙個序號,第乙個位元組的編號由本地隨機產生 給位元組編上序號後,就給每乙個報文...
TCP建立連線三次握手和釋放連線四次握手
尊重在談及tcp建立連線和釋放連線過程,先來簡單認識一下tcp報文段首部格式的的幾個名詞 這裡只是簡單說明,具體請檢視相關教程 序列號seq 佔4個位元組,用來標記資料段的順序,tcp把連線中傳送的所有資料位元組都編上乙個序號,第乙個位元組的編號由本地隨機產生 給位元組編上序號後,就給每乙個報文段指...