TCP: 一種面向來連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。
- 面向連接: 數(shù)據(jù)在發(fā)送之前必須在兩端建立連接,方法就是我們熟知的三次握手連接。
- 可靠傳輸: 通過多種機制來保證數(shù)據(jù)的正確傳輸,比如序列號/確認應答機制、檢驗和機制、超時重傳機制、流量控制、擁塞避免機制等。
- 基于字節(jié)流: 雖然應用程序和TCP的交互是一次一個數(shù)據(jù)塊(大小不等),但TCP把應用程序看成是一連串的無結構的字節(jié)流。TCP有一個緩沖,當應用程序傳送的數(shù)據(jù)塊太長,TCP就可以把它劃分短一些再傳送。如果應用程序一次只發(fā)送一個字節(jié),TCP也可以等待積累有足夠多的字節(jié)后再構成報文段發(fā)送出去。
特點:
- 面向連接
- 僅支持單播傳輸
- 面向字節(jié)流
- 可靠傳輸
- 提供全雙工通信
TCP的三次握手:
1、客戶端向服務器申請建立TCP連接,向服務發(fā)送一個SYN報文,作為第一次握手??蛻舳税堰@段連接的SYN設定為隨機數(shù)A。
2、服務器端收到SYN報文后,會向客戶端發(fā)送一個報文。報文中ACK的確認碼為A+1,同時發(fā)送另一個SYN為隨機序號B。
3,此時,客戶端收到ACK為A+1的報文,將之與發(fā)送的SYN包進行比對,如果滿足+1的關系,則在客戶端判斷連接已建立。并給服務器發(fā)送確認數(shù)據(jù)包,SYN為A+1,表明已收到上一報文,ACk為B+1,通知服務器進入連接狀態(tài)。
TCP的四次揮手:
1、客戶端向服務器發(fā)送一個FIN報文,作為第一次揮手。通知服務器,我已經(jīng)沒有數(shù)據(jù)還要發(fā)送。但不確認服務器是否仍有數(shù)據(jù)返回,所以連接仍是建立狀態(tài)。
2、服務器收到FIN報文,返回一個ACK報文,告訴客戶端,我知道你已經(jīng)沒有東西要發(fā)送了,但我還要再確認一下我是不是還有東西要給你。
3、服務器判斷自己也沒有報文需要發(fā)送給客戶端,發(fā)送FIN報文,告訴客戶端,好了,這下我也沒有東西要給你了,你可以終結連接了。此時服務器不確認客戶端是否收到信息,繼續(xù)保持連接。
4、客戶端收到ACK和FIN消息后,得知服務器已經(jīng)知道自己要終結,并無更新內(nèi)容,便給服務器發(fā)送一個ACK說我知道了,你也終結吧,客戶機便終結連接。服務器在收到一條ACK后,也終結連接。
面試題:
- 為什么連接的時候是三次握手,關閉的時候卻是四次握手?
因為當Server端收到Client端的SYN連接請求報文后,可以直接發(fā)送SYN+ACK報文。
其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連接時,當Server端收到FIN報文時,很可能并不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,"你發(fā)的FIN報文我收到了"。
只有等到我Server端所有的報文都發(fā)送完了,我才能發(fā)送FIN報文,因此不能一起發(fā)送。故需要四步握手。
- 為什么TIME_WAIT狀態(tài)需要經(jīng)過2MSL(最大報文段生存時間)才能返回到CLOSE狀態(tài)?
按道理,四個報文都發(fā)送完畢,我們可以直接進入CLOSE狀態(tài)了,但是我們必須假象網(wǎng)絡是不可靠的,有可以最后一個ACK丟失。所以TIME_WAIT狀態(tài)就是用來重發(fā)可能丟失的ACK報文。
在Client發(fā)送出最后的ACK回復,但該ACK可能丟失。Server如果沒有收到ACK,將不斷重復發(fā)送FIN片段。所以Client不能立即關閉,它必須確認Server接收到了該ACK。Client會在發(fā)送出ACK之后進入到TIME_WAIT狀態(tài)。Client會設置一個計時器,等待2MSL的時間。如果在該時間內(nèi)再次收到FIN,那么Client會重發(fā)ACK并再次等待2MSL。
所謂的2MSL是兩倍的MSL(Maximum Segment Lifetime)。MSL指一個片段在網(wǎng)絡中最大的存活時間,2MSL就是一個發(fā)送和一個回復所需的最大時間。
如果直到2MSL,Client都沒有再次收到FIN,那么Client推斷ACK已經(jīng)被成功接收,則結束TCP連接。
- 為什么不能用兩次握手進行連接?
3次握手完成兩個重要的功能,既要雙方做好發(fā)送數(shù)據(jù)的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始序列號進行協(xié)商,這個序列號在握手過程中被發(fā)送和確認。
現(xiàn)在把三次握手改成僅需要兩次握手,死鎖是可能發(fā)生的。作為例子,考慮計算機S和C之間的通信,假定C給S發(fā)送一個連接請求分組,S收到了這個分組,并發(fā) 送了確認應答分組。按照兩次握手的協(xié)定,S認為連接已經(jīng)成功地建立了,可以開始發(fā)送數(shù)據(jù)分組??墒牵珻在S的應答分組在傳輸中被丟失的情況下,將不知道S 是否已準備好,不知道S建立什么樣的序列號,C甚至懷疑S是否收到自己的連接請求分組。在這種情況下,C認為連接還未建立成功,將忽略S發(fā)來的任何數(shù)據(jù)分 組,只等待連接確認應答分組。而S在發(fā)出的分組超時后,重復發(fā)送同樣的分組。這樣就形成了死鎖。
- 如果已經(jīng)建立了連接,但是客戶端突然出現(xiàn)故障了怎么辦?
CP還設有一個保活計時器,顯然,客戶端如果出現(xiàn)故障,服務器不能一直等下去,白白浪費資源。服務器每收到一次客戶端的請求后都會重新復位這個計時器,時間通常是設置為2小時,若兩小時還沒有收到客戶端的任何數(shù)據(jù),服務器就會發(fā)送一個探測報文段,以后每隔75秒鐘發(fā)送一次。若一連發(fā)送10個探測報文仍然沒反應,服務器就認為客戶端出了故障,接著就關閉連接。
- 在握手與揮手的過程中,往復的ack與seq有什么含義?
這是通信雙方在通信過程中的一種確認手段,確保通信雙方通信的正確性。例如小時候模仿電視劇里無線電呼叫的過程:“土豆土豆,我是地瓜,你能聽到嗎?”“地瓜地瓜,我是土豆,我能聽到”。 若客戶端的報文請求號為“土豆”,則服務器端就將返回確認號“土豆+1”(標志土豆已收到),是一種通信雙方的確認手段。
- 在結束連接的過程中,為什么在收到服務器端的連接釋放報文段之后,客戶端還要繼續(xù)等待2MSL之后才真正關閉TCP連接呢?
① 需要保證服務器端收到了客戶端的最后一條確認報文。假如這條報文丟失,服務器沒有接收到確認報文,就會對連接釋放報文進行超時重傳,而此時客戶端連接已關閉,無法做出響應,就造成了服務器端不停重傳連接釋放報文,而無法正常進入關閉狀態(tài)的狀況。而等待2MSL,就可以保證服務器端收到了最終確認;若服務器端沒有收到,那么在2MSL之內(nèi)客戶端一定會收到服務器端的重傳報文,此時客戶端就會重傳確認報文,并重置計時器。
②存在一種“已失效的連接請求報文段”,需要避免這種報文端出現(xiàn)在本連接中,造成異常。這種“已失效的連接請求報文段”是這么形成的:假如客戶端發(fā)出了連接請求報文,然而服務器端沒有收到,于是客戶端進行超時重傳,再一次發(fā)送了連接請求報文,并成功建立連接。然而,第一次發(fā)送的連接請求報文并沒有丟失,只是在某個網(wǎng)絡結點中發(fā)生了長時間滯留,隨后,這個最初發(fā)送的報文段到達服務器端,會使得服務器端誤以為客戶端發(fā)出了新的請求,造成異常。
- 若通信雙方同時請求連接或同時請求釋放連接,情況如何?
這種情況雖然發(fā)生的可能性極小,但是是確實存在的,TCP也特意設計了相關機制,使得在這種情況下雙方僅建立一條連接。雙方同時請求連接的情況下,雙方同時發(fā)出請求連接報文,并進入SYN-SENT狀態(tài);當收到對方的請求連接報文后,會再次發(fā)送請求連接報文,確認號為對方的SYN+1,并進入SYN-RCVD狀態(tài);當收到對方第二次發(fā)出的攜帶確認號的請求報文之后,會進入ESTAB-LISHED狀態(tài)。 雙方同時請求釋放連接也是同樣的,雙方同時發(fā)出連接釋放報文,并進入FIN-WAIT-1狀態(tài);在收到對方的報文之后,發(fā)送確認報文,并進入CLOSING狀態(tài);在收到對方的確認報文后,進入TIME-WAIT狀態(tài),等待2MSL之后關閉連接。需要注意的是,這個時候雖然不用再次發(fā)送確認報文并確認對方收到,雙方仍需等待2MSL之后再關閉連接,是為了防止“已失效的連接請求報文段”的影響
如果此文對你有用請動動你的小手點個贊!謝謝?。?!