源埠和目的埠:各佔2個位元組,分別寫入源埠號和目的埠號(tcp報文需要的是埠號,往下封裝會在ip報文中新增上源ip和目的ip)
序號: 4個位元組,[0-了2^32-1]一共有2^32個序號,因為tcp是面向位元組流;在乙個tcp連線中傳送的位元組流中的每乙個位元組都按順序編號;整個要傳送的位元組流的起始序號必須在連線建立的時候設定(也就是一開始三次握手的時候傳送的syn包中的seq欄位部分)。tcp報文中的首部的序號欄位則是本報文段所傳送的資料的第乙個位元組的序號。
確認號:ack;4個位元組,表示的是期望收到對方下乙個報文段的第乙個資料位元組的序號;比如說,b正確的收到了a傳送過來的乙個報文段,其序號字段值為501,且資料的長度為200位元組(501-700),這表明b正確受到了a傳送的到序號700為止的資料,因此b希望收到a的下乙個資料序號是701;所以ack=701。
總之,若確認號為n,則表明到序號n-1為止的所有資料已經正確接收。
確認ack:僅當ack=1時,確認號字段(ack)有效,當ack=0的時候,確認號字段無效。tcp規定,在連線建立後所有傳送的報文段的ack都置1。
終止fin:用來釋放乙個連線,當fin=1的時候表明此報文段的傳送方的資料已經傳送完畢,並且要求釋放連線。
視窗:佔2個位元組,值在[0-2^16-1]之間的整數,指的是傳送本報文段的一方的接收視窗(而不是自己的傳送視窗),視窗值主要是用來告訴對方:從本報文段首部中的確認號算起,我目前的允許對方傳送的資料量——主要是用來解決防止傳送方傳送資料過快而來不及接收,總之視窗值作為接收方讓傳送方設定其傳送視窗大小的依據。
(ps:來自這位大佬的部落格)
tcp伺服器程序先建立傳輸控制塊tcb,準備接受客戶端程序的連線請求,然後伺服器程序就處於listen(監聽)狀態,等待客戶端的連線請求。
tcp客戶端程序也是先建立傳輸控制塊tcb,然後向伺服器端傳送連線請求報文。
第一次握手:
客戶端傳送syn包(syn=1,seq=x)給伺服器端,等待伺服器的確認,進入syn_send(同步已傳送)狀態。
解釋:第一次握手客戶端傳送的syn包中,syn是同步序列編號,需要設定為1,seq是用於建立連線之後通訊所用的,表示的是建立連線後要傳輸的資料的起始序號,tcp規定,雖然第一次握手傳送的syn包沒有攜帶資料,但是也要占用乙個序號,即客戶端傳送資料的時候只能用x+1開始傳送。
第二次握手:
伺服器接收到客戶端傳送的syn包,如果同意建立連線,那麼就傳送了乙個確認報文段(ack=1,ack=x+1,syn=1,seq=y),進入syn_recv(同步收到)狀態。
解釋:第二次握手中的ack=1是為了讓確認號字段ack有效,而ack=x+1表明的是伺服器方已經成功接收到客戶端傳送的到x為止(包括x)的所有資料;並且希望下一次收到客戶端傳送過來的資料是從x+1開始;同時由於是全雙工的通訊,伺服器端設定syn=1,seq=y,用於建立連線後的傳送資料的起始序號;tcp規定:雖然這份確認報文段不攜帶資料,但是也要占用乙個序號的位置。
第三次握手:
客戶端接收到伺服器端傳送的確認報文段,並且向伺服器傳送ack確認報文段(seq=x+1,ack=y+1,ack=1),此時,tcp連線建立,客戶端進入established(已建立連線)狀態。
解釋:第三次握手客戶端傳送了ack確認報文(ack=1,ack=y+1,seq=x+1),ack=1和ack=y+1表示對伺服器傳送的確認報文段的乙個確認,同時希望下次收到的資料的起始序號從y+1開始,tcp規定:本次的ack確認報文段可以攜帶資料,但是如果不攜帶資料則不消耗序號。
**為了確保通訊雙方的傳送資訊和接收資訊的能力沒問題。
假設客戶端為a,伺服器端為b
1.一開始a傳送syn包給b,b收到了a傳送的syn包
---->b自己就會覺得,自己的接收資訊能力沒問題。
2.b傳送確認報文段給a,並且a收到b傳送的包
---->a收到了包之後,首先因為b不會無端端傳送資訊給a,a就會知道剛剛自己
成功傳送了資訊b,說明a自己的傳送能力沒問題,其次是a現在接收到了b的
包,證明a自己的接收能力也沒問題。但是這個時候b並不知道自己的傳送能力怎麼樣,所以需要再a傳送多一次進行多一次握手才可以。
3.a再傳送ack包給b
---->b目前還不知道自己的傳送能力怎麼樣,直到a傳送了確認包回來,那麼就說
明b自己的傳送能力沒問題。
好~~開心的通訊吧~~
(ps:來自這位大佬的部落格)
1.客戶端程序發出連線釋放報文(fin包),並且停止傳送資料。釋放資料報文首部,fin=1,其序列號為seq=u(等於前面已經傳送過來的資料的最後乙個位元組的序號加1),此時,客戶端進入fin-wait-1(終止等待1)狀態。 tcp規定,fin報文段即使不攜帶資料,也要消耗乙個序號。
2.伺服器收到連線釋放報文,發出確認報文,ack=1,ack=u+1(表示對u+1之前的傳送的資料進行乙個確認),並且帶上自己的序列號seq=v(因為由於是客戶端提出的關閉連線;但是伺服器端可能還有資料沒有傳送完),此時,服務端就進入了close-wait(關閉等待)狀態。tcp伺服器通知高層的應用程序,客戶端向伺服器的方向就釋放了,這時候處於半關閉狀態,即客戶端已經沒有資料要傳送了,但是伺服器若傳送資料,客戶端依然要接受。
這個狀態還要持續一段時間,也就是整個close-wait狀態持續的時間
3.客戶端收到伺服器的確認請求後,此時,客戶端就進入fin-wait-2(終止等待2)狀態,等待伺服器傳送連線釋放報文(在這之前還需要接受伺服器傳送的最後的資料)。
4.伺服器將最後的資料傳送完畢後,就向客戶端傳送連線釋放報文,fin=1,ack=u+1,由於在半關閉狀態,伺服器很可能又傳送了一些資料,假定此時的序列號為seq=w,此時,伺服器就進入了last-ack(最後確認)狀態,等待客戶端的確認(w-v得到的就是伺服器方在這段時間傳送的資料的總量。)
5.客戶端收到伺服器的連線釋放報文後,必須發出確認,ack=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了time-wait(時間等待)狀態。注意此時tcp連線還沒有釋放,必須經過2∗
'>∗
∗msl(最長報文段壽命)的時間後,當客戶端撤銷相應的tcb後,才進入closed狀態。
∗'>6.
伺服器只要收到了客戶端發出的確認,立即進入closed狀態。同樣,撤銷tcb後,就結束了這次的tcp連線。可以看到,伺服器結束tcp連線的時間要比客戶端早一些。
msl(maximum segment lifetime),tcp允許不同的實現可以設定不同的msl值。
第一,保證客戶端傳送的最後乙個ack報文能夠到達伺服器,因為這個ack報文可能丟失,站在伺服器的角度看來,我已經傳送了fin+ack報文請求斷開了,客戶端還沒有給我回應,應該是我傳送的請求斷開報文它沒有收到,於是伺服器又會重新傳送一次,而客戶端就能在這個2msl時間段內收到這個重傳的報文,接著給出回應報文,並且會重啟2msl計時器。
第二,防止類似與「三次握手」中提到了的「已經失效的連線請求報文段」出現在本連線中。客戶端傳送完最後乙個確認報文後,在這個2msl時間中,就可以使本連線持續的時間內所產生的所有報文段都從網路中消失。這樣新的連線中不會出現舊連線的請求報文。
為什麼建立連線是三次握手,關閉連線確是四次揮手呢?
建立連線的時候, 伺服器在listen狀態下,收到建立連線請求的syn報文後,把ack和syn放在乙個報文裡傳送給客戶端。
而關閉連線時,伺服器收到對方的fin報文時,僅僅表示對方不再傳送資料了但是還能接收資料,而自己也未必全部資料都傳送給對方了,所以己方可以立即關閉,也可以傳送一些資料給對方後,再傳送fin報文給對方來表示同意現在關閉連線,因此,己方ack和fin一般都會分開傳送,從而導致多了一次。
tcp還設有乙個保活計時器,顯然,客戶端如果出現故障,伺服器不能一直等下去,白白浪費資源。伺服器每收到一次客戶端的請求後都會重新復位這個計時器,時間通常是設定為2小時,若兩小時還沒有收到客戶端的任何資料,伺服器就會傳送乙個探測報文段,以後每隔75分鐘傳送一次。若一連傳送10個探測報文仍然沒反應,伺服器就認為客戶端出了故障,接著就關閉連線。
三次握手和四次揮手
三次握手和四次揮手如圖所示 為什麼是三次握手而不是兩次 因為當客戶端第傳送syn到服務端的時候,如果有幾次請求是因為網路等原因延時等情況的時候,如果沒有第三次握手的確定。服務端就會認為客戶端重寫傳送請求了,就會去開啟連線相應。為什麼關閉連線的時候是四次握手而不是三次?當客戶端傳送請求關閉連線的時候,...
三次握手和四次揮手
tcp三次握手和四次揮手的全過程 tcp是主機對主機層的傳輸控制協議,提供可靠的連線服務,採用三次握手確認建立乙個連線 位碼即tcp標誌位,有6種表示 syn synchronous建立連線 ack acknowledgement 表示響應 確認 psh push表示有data資料傳輸 fin fi...
三次握手和四次揮手
1.在學習tcp協議的時候,總是在強調三次握手,那麼為什麼是三次?而不是兩次或者四次?強迫症表示黑人問號?今天我們就來分析一下為什麼是三次,下圖是一次tcp通訊的時序 在這個例子中,首先客戶端主動發起連線 傳送請求,然後伺服器端響應請求,然後客戶端主動關閉連線。兩條豎線表示通訊的兩端,從上到下表 示...