【尊重在談及tcp建立連線和釋放連線過程,先來簡單認識一下tcp報文段首部格式的的幾個名詞(這裡只是簡單說明,具體請檢視相關教程)
序列號seq:佔4個位元組,用來標記資料段的順序,tcp把連線中傳送的所有資料位元組都編上乙個序號,第乙個位元組的編號由本地隨機產生;給位元組編上序號後,就給每乙個報文段指派乙個序號;序列號seq就是這個報文段中的第乙個位元組的資料編號。
確認號ack:佔4個位元組,期待收到對方下乙個報文段的第乙個資料位元組的序號;序列號表示報文段攜帶資料的第乙個位元組的編號;而確認號指的是期望接收到下乙個位元組的編號;因此當前報文段最後乙個位元組的編號+1即為確認號。
確認ack:佔1位,僅當ack=1時,確認號字段才有效。ack=0時,確認號無效
同步syn:連線建立時用於同步序號。當syn=1,ack=0時表示:這是乙個連線請求報文段。若同意連線,則在響應報文段中使得syn=1,ack=1。因此,syn=1表示這是乙個連線請求,或連線接受報文。syn這個標誌位只有在tcp建產連線時才會被置1,握手完成後syn標誌位被置0。
終止fin:用來釋放乙個連線。fin=1表示:此報文段的傳送方的資料已經傳送完畢,並要求釋放運輸連線
ps:ack、syn和fin這些大寫的單詞表示標誌位,其值要麼是1,要麼是0;ack、seq小寫的單詞表示序號。
一、tcp建立連線三次握手
(1)、三次握手的過程
1)主機a向主機b傳送tcp連線請求資料報,其中包含主機a的初始序列號seq(a)=x。(其中報文中同步標誌位syn=1,ack=0,表示這是乙個tcp連線請求資料報文;序號seq=x,表明傳輸資料時的第乙個資料位元組的序號是x);
2)主機b收到請求後,會發回連線確認資料報。(其中確認報文段中,標識位syn=1,ack=1,表示這是乙個tcp連線響應資料報文,並含主機b的初始序列號seq(b)=y,以及主機b對主機a初始序列號的確認號ack(b)=seq(a)+1=x+1)
3)第三次,主機a收到主機b的確認報文後,還需作出確認,即傳送乙個序列號seq(a)=x+1;確認號為ack(a)=y+1的報文;
(2)為什麼需要第三次握手?
還要再傳送一次確認是為了,防止已失效的連線請求報文段突然又傳到了b,因而產生錯誤。
已失效的報文段:正常情況下:a發出連線請求,但因為丟失了,故而不能收到b的確認。於是a重新發出請求,然後收到確認,建立連線,資料傳輸完畢後,釋放連線,a發了2個,乙個丟掉,乙個到達,沒有「已失效的報文段」
但是,某種情況下,a的第乙個在某個節點滯留了,延誤到達,本來這是乙個早已失效的報文段,但是在a傳送第二個,並且得到b的回應,建立了連線以後,這個報文段竟然到達了,於是b就認為,a又傳送了乙個新的請求,於是傳送確認報文段,同意建立連線,假若沒有三次的握手,那麼這個連線就建立起來了(有乙個請求和乙個回應),此時,a收到b的確認,但a知道自己並沒有傳送建立連線的請求,因為不會理睬b的這個確認,於是呢,a也不會傳送任何資料,而b呢卻以為新的連線建立了起來,一直等待a傳送資料給自己,此時b的資源就被白白浪費了。但是採用三次握手的話,a就不傳送確認,那麼b由於收不到確認,也就知道並沒有要求建立連線。
簡而言之:第三次握手,主機a傳送一次確認是為了防止:如果客戶端遲遲沒有收到伺服器返回的確認報文,這時他會放棄連線,重新啟動一條連線請求;但問題是:伺服器不知客戶端沒收到,所以他會收到兩個連線請求,白白浪費了一條連線開銷。
二、tcp釋放連線四次握手
(1)四次握手過程
假設主機a為客戶端,主機b為伺服器,其釋放tcp連線的過程如下:
1) 關閉客戶端到伺服器的連線:首先客戶端a傳送乙個fin,用來關閉客戶到伺服器的資料傳送,然後等待伺服器的確認。其中終止標誌位fin=1,序列號seq=u
2) 伺服器收到這個fin,它發回乙個ack,確認號ack為收到的序號加1。
3) 關閉伺服器到客戶端的連線:也是傳送乙個fin給客戶端。
4) 客戶段收到fin後,並發回乙個ack報文確認,並將確認序號seq設定為收到序號加1。
首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。
主機a傳送fin後,進入終止等待狀態, 伺服器b收到主機a連線釋放報文段後,就立即給主機a傳送確認,然後伺服器b就進入close-wait狀態,此時tcp伺服器程序就通知高層應用程序,因而從a到b的連線就釋放了。此時是「半關閉」狀態。即a不可以傳送給b,但是b可以傳送給a。
此時,若b沒有資料報要傳送給a了,其應用程序就通知tcp釋放連線,然後傳送給a連線釋放報文段,並等待確認。a傳送確認後,進入time-wait,注意,此時tcp連線還沒有釋放掉,然後經過時間等待計時器設定的2msl後,a才進入到close狀態。
(2)為什麼要等待2msl呢?
msl即maximum segment lifetime,也就是最大報文生存時間,他是任何報文在網路上存在的最長時間,超過這個時間報文將被丟棄。引用《tcp/ip詳解》中的話:「它(msl)是任何報文段被丟棄前在網路內的最長時間」。rfc 793中規定msl為2分鐘,實際應用中常用的是30秒,1分鐘和2分鐘等。
tcp的time_wait狀態需要等待2msl,當tcp的一端發起主動關閉,在發出最後乙個ack包後,即第3次握手完成後傳送了第四次握手的ack包後就進入了time_wait狀態,必須在此狀態上停留兩倍的msl時間,等待2msl時間主要目的是怕最後乙個ack包對方沒收到,那麼對方在超時後將重發第三次握手的fin包,主動關閉端接到重發的fin包後可以再發乙個ack應答包。在time_wait狀態時兩端的埠不能使用,要等到2msl時間結束才可繼續使用。當連線處於2msl等待階段時任何遲到的報文段都將被丟棄。不過在實際應用中可以通過設定so_reuseaddr選項達到不必等待2msl時間結束再使用此埠。
概括原因如下:
①、為了保證a傳送的最後乙個ack報文段能夠到達b。即最後這個確認報文段很有可能丟失,那麼b會超時重傳,然後a再一次確認,同時啟動2msl計時器,如此下去。如果沒有等待時間,傳送完確認報文段就立即釋放連線的話,b就無法重傳了(連線已被釋放,任何資料都不能出傳了),因而也就收不到確認,就無法按照步驟進入close狀態,即必須收到確認才能close。
②、防止「已失效的連線請求報文段」出現在連線中。經過2msl,那些在這個連線持續的時間內,產生的所有報文段就可以都從網路中消失。即在這個連線釋放的過程中會有一些無效的報文段滯留在樓閣結點,但是呢,經過2msl這些無效報文段就肯定可以傳送到目的地,不會滯留在網路中。這樣的話,在下乙個連線中就不會出現上乙個連線遺留下來的請求報文段了。
可以看出:b結束tcp連線的時間比a早一點,因為b收到確認就斷開連線了,而a還得等待2msl.
(3)為什麼tcp釋放連線需要四次?
tcp建立連線要進行三次握手,而斷開連線要進行四次。這是由於tcp的半關閉造成的。因為tcp連線是全雙工的(即資料可在兩個方向上同時傳遞)所以進行關閉時每個方向上都要單獨進行關閉。這個單方向的關閉就叫半關閉。當一方完成它的資料傳送任務,就傳送乙個fin來向另一方通告將要終止這個方向的連線。
注意:
1)傳送了fin只是表示這端不能繼續傳送資料(應用層不能再呼叫send傳送),但是還可以接收資料。收到乙個 fin只意味著這一方向上沒有資料流動,乙個tcp連線在收到乙個fin後仍能傳送資料,比如:如主機a收到主機b的fin斷開tcp連線請求,只是表示主機b已經傳送完資料,主機a收到fin後作出應答,並終止這個方向的資料傳輸,此時處於半關閉狀態。但是主機a仍然可以傳送資料的,只有當主機a傳送完資料並傳送fin給主機b時,主機b才停止這個方向的資料傳輸,並關閉tcp連線。
2)在很多時候,tcp連線的斷開都會由tcp層自動進行,例如你ctrl+c終止你的程式,tcp連線依然會正常關閉,你可以寫**試試。
TCP建立連線三次握手和釋放連線四次握手
尊重 在談及tcp建立連線和釋放連線過程,先來簡單認識一下 tcp報文段首部格式 的的幾個名詞 這裡只是簡單說明,具體請檢視相關教程 序列號seq 佔4個位元組,用來標記資料段的 順序,tcp把連線中傳送的所有資料位元組都編上乙個序號,第乙個位元組的編號由本地隨機產生 給位元組編上序號後,就給每乙個...
TCP建立連線三次握手和釋放連線四次握手
尊重 在談及tcp建立連線和釋放連線過程,先來簡單認識一下tcp報文段首部格式 的的幾個名詞 這裡只是簡單說明,具體請檢視相關教程 序列號seq 佔4個位元組,用來標記資料段的順序,tcp把連線中傳送的所有資料位元組都編上乙個序號,第乙個位元組的編號由本地隨機產生 給位元組編上序號後,就給每乙個報文...
TCP建立連線(三次握手)和釋放連線(四次握手)
建立乙個自定義列表 如何建立乙個註腳 注釋也是必不可少的 katex數學公式 新的甘特圖功能,豐富你的文章 uml 圖表 flowchart流程圖 匯出與匯入 1 三次握手 建立連線 第一次握手 客戶端傳送syn包 syn x 到伺服器,並進入syn send狀態,等待伺服器確認 第二次握手 伺服器...