首先要先了解TCP資料包的一些欄位的作用: 這里只列出了用到的幾個重要的,

- 序號(seq):占4個位元組,32位, 發送端告訴接收端這組的首部第一個是第多少個位元組,
一整個資料包要放到緩沖區中分組傳輸,分組之后的每個資料包都要加上TCP首部,這里表明發送方發送該組的第一個位元組是一整個大資料包(沒有放緩沖區的分組之前的整個資料包)的第多少個位元組,
- 確認號(ack):占4個位元組,32位,接收端告訴發送端我已經收到了多少位元組,該發下一個位元組了(該位為,收到的位元組數+1),
- ACK:占1位,如果該位為0,表示確認號無效,如果是1表示確認號有效,
- SYN:占1位,請求建立會話連接,當SYN=1時表示同意建立會話,
SYN=1,ACK=0 :表示請求連接的的資料包,其實ACK是沒有,
SYN=1,ACK=1 :表示回應同意建立連接的資料包,
1.三次握手:
就是在進行可靠傳輸發送資料之前,要連續三次打招呼建立連接的程序,- 三次握手的程序:
第一次握手:在每次發送之前客戶端都會向服務端發送SYN(seq=x)資料包請求建立連接,客戶端進入SYN_SENT狀態,
第二次握手:服務器收到SYN包,必須確認客戶的SYN(ack=x+1),同時自己也發送一個SYN包(seq=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態
第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED(TCP連接成功)狀態,完成三次握手,
簡單理解三次握手:
TCP的三次握手還是挺有意思的,基本思想就是“讓我知道你已經知道”了,
服務器監聽請求,客戶端發起連接請求(第一次握手:客戶端->服務端:客戶端請求建立連接),請求在路上可能存在丟失的風險, 所以當請求到了服務器后如果服務器同意建立連接會給客戶端一個回信(第二次握手:服務端->客戶端:服務端同意建立連接),告訴它:我已經收到請求,可以連接, 但是回信也存在一個問題,那就是回信能不能到客戶端?它需要客戶端給他一個回信說我已經收到批準通知了, 如果客戶端一直不回復的話意味著客戶端沒有收到批準通知, 因此客戶端一收到批準通知就立馬回復(第三次握手:客戶端->服務端:客戶端收到了服務端的同意連接的資料包):OK老鐵我收到你的批準通知了,
三次握手結束,服務端開始進行可靠傳輸發送資料,
- 三次握手的作用:
2.四次揮手:
就是連續四次告別,即終止TCP連接的程序,
- 四次揮手的程序:
![]() |
FIN_WAIT_2:上面已經詳細解釋了這種狀態,實際上FIN_WAIT_2狀態下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點資料需要傳送給你,稍后再關閉連接, |
| TIME_WAIT: 表示收到了對方的FIN報文,并發送出了ACK報文,就等2MSL后即可回到CLOSED可用狀態了,如果FIN_WAIT_1狀態下,收到了對方同時帶 FIN標志和ACK標志的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態, | |
| CLOSING: 這種狀態比較特殊,實際情況中應該是很少見,屬于一種比較罕見的例外狀態,正常情況下,當你發送FIN報文后,按理來說是應該先收到(或同時收到)對方的 ACK報文,再收到對方的FIN報文,但是CLOSING狀態表示你發送FIN報文后,并沒有收到對方的ACK報文,反而卻也收到了對方的FIN報文,什 么情況下會出現此種情況呢?其實細想一下,也不難得出結論:那就是如果雙方幾乎在同時close一個SOCKET的話,那么就出現了雙方同時發送FIN報 文的情況,也即會出現CLOSING狀態,表示雙方都正在關閉SOCKET連接, | |
| FIN_WAIT_1: 其實FIN_WAIT_1和FIN_WAIT_2狀態的真正含義都是表示等待對方的FIN報文,而這兩種狀態的區別 是:FIN_WAIT_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉連接,向對方發送了FIN報文,此時該SOCKET即 進入到FIN_WAIT_1狀態,而當對方回應ACK報文后,則進入到FIN_WAIT_2狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬 上回應ACK報文,所以FIN_WAIT_1狀態一般是比較難見到的,而FIN_WAIT_2狀態還有時常常可以用netstat看到, | CLOSE_WAIT: 這種狀態的含義其實是表示在等待關閉,怎么理解呢?當對方close一個SOCKET后發送FIN報文給自己,你系統毫無疑問地會回應一個ACK報文給對 方,此時則進入到CLOSE_WAIT狀態,接下來呢,實際上你真正需要考慮的事情是察看你是否還有資料發送給對方,如果沒有的話,那么你也就可以 close這個SOCKET,發送FIN報文給對方,也即關閉連接,所以你在CLOSE_WAIT狀態下,需要完成的事情是等待你去關閉連接, |
| LAST_ACK: 這個狀態還是比較容易好理解的,它是被動關閉一方在發送FIN報文后,最后等待對方的ACK報文,當收到ACK報文后,也即可以進入到CLOSED可用狀態了, |
3.三次握手和四次揮手中的常見問題:
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個探測報文仍然沒反應,服務器就認為客戶端出了故障,接著就關閉連接,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/71770.html
標籤:其他
上一篇:風力發電電力監控系統介紹

