TCP協(xié)議
TCP協(xié)議,即傳輸控制協(xié)議(英文全拼:Transmission Control Protocol)。 其是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。 TCP通信需要經(jīng)過創(chuàng)建連接、傳送數(shù)據(jù)、終止連接三個步驟。在通信傳輸之前,先要打開一個連接,連接關(guān)閉后無法再發(fā)送數(shù)據(jù)。
TCP通信類似生活中的“打電話”,打電話之前,必須要先撥打?qū)Ψ降碾娫捥柎a請求建立連接,接通后雙方才能通信,而電話掛斷后就不能再進行通信了。
TCP特點
1.面向連接
進行TCP通信的雙方必須先建立連接,然后才能進行數(shù)據(jù)的傳輸,雙方都必須為該連接分配必要的系統(tǒng)內(nèi)核資源,以管理連接的狀態(tài)和連接上的傳輸。 雙方間的數(shù)據(jù)傳輸都在這一個連接上進行。完成數(shù)據(jù)交換后,雙方必須斷開此連接,以釋放系統(tǒng)資源。并且這種連接是一對一的。
2.可靠傳輸
TCP通過4種機制實現(xiàn)可靠傳輸:
1)TCP采用發(fā)送應(yīng)答機制
TCP發(fā)送的每個報文段都必須得到接收方的應(yīng)答,如此才會認(rèn)為這個TCP報文段傳輸成功。
2)超時重傳
發(fā)送端發(fā)出一個報文段之后就啟動定時器,如果在定時時間內(nèi)沒有收到應(yīng)答就重新發(fā)送這個報文段。
TCP為了保證不發(fā)生丟包,就給每個包一個序號,序號也保證了傳送到接收端實體的包的按序接收。然后接收端實體對已成功收到的包發(fā)回一個相應(yīng)的確認(rèn)(ACK)。如果發(fā)送端實體在合理的往返時延(RTT)內(nèi)未收到確認(rèn),那么就會假設(shè)對應(yīng)的數(shù)據(jù)包已丟失將會進行重傳。
3)錯誤校驗
TCP用一個校驗和函數(shù)來檢驗數(shù)據(jù)是否有錯誤,在發(fā)送和接收時都要計算校驗和。
4)流量控制和阻塞管理
流量控制用來避免主機發(fā)送得過快而使接收方來不及完全收下。
3.基于字節(jié)流
TCP是一種流模式協(xié)議(steam protocol),數(shù)據(jù)是以字節(jié)流的形式進行傳輸?shù)?,其中傳送的字?jié)流中的每個字節(jié)都按順序編號。
TCP發(fā)送字節(jié)流數(shù)據(jù)流程:
(1)先將某次發(fā)送的數(shù)據(jù)作為一個數(shù)據(jù)塊暫存到發(fā)送緩存區(qū),發(fā)送時在緩存區(qū)先后打包成TCP報文段和IP數(shù)據(jù)包后發(fā)送(由于緩存區(qū)不止存在此次發(fā)送的數(shù)據(jù),一個數(shù)據(jù)塊可能會被分割成一部分與其他數(shù)據(jù)塊一同被打包成TCP報文段);
(2)TCP報文段包含TCP首部和TCP數(shù)據(jù)兩部分,首部包含源端口號和目的端口號、字節(jié)序號及確認(rèn)號等信息;該TCP報文段被進一步包裝,成為IP報文段,包含IP首部和IP數(shù)據(jù)部分,IP首部包含源IP地址和目的IP地址等信息,IP數(shù)據(jù)部分即是TCP報文段;

(3)網(wǎng)絡(luò)鏈路層會根據(jù)源IP地址、目的IP地址和源端口號、目的端口號確定連接的雙方,把IP數(shù)據(jù)包發(fā)送到接收端的接收緩存區(qū);
(4)接收端應(yīng)用程序從接收緩存區(qū)讀取數(shù)據(jù)塊,根據(jù)字節(jié)序號將數(shù)據(jù)重組成完整數(shù)據(jù),即成功接收到消息;

簡要總結(jié)一下TCP即是:TCP協(xié)議是建立在IP協(xié)議之上的,負(fù)責(zé)在兩臺計算機之間建立可靠連接,保證數(shù)據(jù)包按順序到達。
建立TCP連接-3次握手
建立一個TCP連接時,需要客戶端和服務(wù)端進行“3次握手”,以確認(rèn)建立連接?!?次握手”是對客戶端和服務(wù)端通過發(fā)3個包來確認(rèn)建立連接的比喻。
3次握手的流程如下圖所示:

(1)第一次握手:Client將標(biāo)志位SYN置為1,隨機產(chǎn)生一個值seq=J,并將該數(shù)據(jù)包發(fā)送給Server,Client進入SYN_SENT狀態(tài),等待Server確認(rèn);
(2)第二次握手:Server收到數(shù)據(jù)包后由標(biāo)志位“SYN=1”知道Client請求建立連接,Server將標(biāo)志位SYN和ACK都置為1,ack=J+1,隨機產(chǎn)生一個值seq=K,并將該數(shù)據(jù)包發(fā)送給Client以確認(rèn)連接請求,Server進入SYN_RCVD狀態(tài);
(3)第三次握手:Client收到確認(rèn)后,檢查ack是否為J+1,ACK是否為1,如果正確則將標(biāo)志位ACK置為1,ack=K+1,并將該數(shù)據(jù)包發(fā)送給Server,Server檢查ack是否為K+1,ACK是否為1,如果正確則連接建立成功,Client和Server進入ESTABLISHED狀態(tài),完成三次握手,隨后Client與Server之間可以開始傳輸數(shù)據(jù)了。
為何非要3次握手?
一次、兩次握手建立連接的不可行性:
1)一次握手建立連接,即客戶端發(fā)送一個請求連接的數(shù)據(jù)包即建立連接:由于TCP協(xié)議的接收應(yīng)答機制,一次握手肯定不行,一方面服務(wù)端可能沒有接收到這個請求,另一方面客戶端也無法知曉服務(wù)端是否接收到了這個請求;在這種情形下建立的連接非常不可靠,可能只是客戶端單方面的分配連接資源,而服務(wù)端完全不知道情形;
2)兩次握手建立連接,即客戶端和服務(wù)端各發(fā)送一個數(shù)據(jù)包即建立連接:第一次握手是客戶端請求建立連接,第二次握手是服務(wù)端響應(yīng)連接請求,然后服務(wù)端即分配資源建立連接。但是服務(wù)端的響應(yīng)連接請求的信號客戶端可能沒有接收到,由于TCP協(xié)議的接收應(yīng)答機制,客戶端會再次發(fā)出建立連接的請求,這樣服務(wù)端又會再次分配資源建立連接,而前一次連接就會是占系統(tǒng)用資源的無效連接。假設(shè)服務(wù)端每次發(fā)送的數(shù)據(jù)一直在丟失,客戶端一直SYN,服務(wù)器就會產(chǎn)生多個無效連接,占用資源,這個時候服務(wù)器可能會掛掉。這個現(xiàn)象就是我們聽過的“SYN的洪水攻擊”。
三次握手建立連接的可行性:
第一次握手是客戶端發(fā)起建立連接的請求,然后服務(wù)端響應(yīng)此請求表示可以建立連接進行了第二次握手,最后第三次握手是客戶端對服務(wù)端表示可以建立連接的再次響應(yīng),代表客戶端接收到了服務(wù)端發(fā)出的可以連接的信號。這之后雙方都能確認(rèn)對方接收到了自己的信號,因此可以開始分配資源建立連接傳輸數(shù)據(jù)。三次握手能夠建立可靠的連接。
四次、五次握手的不必要性: 由于三次握手即可以創(chuàng)建可靠的連接了,四次、五次握手就沒有必要了。
形象一點TCP三次握手就像我們打電話,第一方會先“喂,聽得到我說話嗎?”,另一方“嗯,聽到了,你聽得到我說話嗎?”,第一方又說“也聽得到”,雙方都確認(rèn)對方能聽到自己說話后才開始真正的交流。
斷開TCP連接-4次揮手
斷開客戶端和服務(wù)器的TCP連接需要經(jīng)過“四次揮手”。

第一次揮手:主機1(可以是客戶端,也可以是服務(wù)器端),設(shè)置Sequence Number和Acknowledgment Number,向主機2發(fā)送一個FIN報文段;此時,主機1進入FIN_WAIT_1狀態(tài);這表示主機1沒有數(shù)據(jù)要發(fā)送給主機2了;
第二次揮手:主機2收到了主機1發(fā)送的FIN報文段,向主機1回一個ACK報文段,Acknowledgment Number為Sequence Number加1;主機1進入FIN_WAIT_2狀態(tài);
第三次揮手:主機2向主機1發(fā)送FIN報文段,請求關(guān)閉連接,同時主機2進入CLOSE_WAIT狀態(tài);這表示主機2告訴主機1,我也沒有數(shù)據(jù)要發(fā)送了,可以進行關(guān)閉連接了;
第四次揮手:主機1收到主機2發(fā)送的FIN報文段,向主機2發(fā)送ACK報文段,然后主機1進入TIME_WAIT狀態(tài);主機2收到主機1的ACK報文段以后,就關(guān)閉連接;此時,主機1等待2MSL后依然沒有收到回復(fù),則證明Server端已正常關(guān)閉,那好,主機1也可以關(guān)閉連接了。
問題
1.為什么TIME_WAIT狀態(tài)需要經(jīng)過2MSL(最大報文段生存時間)才能返回到CLOSE狀態(tài)?
首先,MSL即Maximum Segment Lifetime,就是最大報文生存時間,是任何報文在網(wǎng)絡(luò)上的存在的最長時間,超過這個時間報文將被丟棄。《TCP/IP詳解》中是這樣描述的:MSL是任何報文段被丟棄前在網(wǎng)絡(luò)內(nèi)的最長時間。RFC 793中規(guī)定MSL為2分鐘,實際應(yīng)用中常用的是30秒、1分鐘、2分鐘等。
TCP的TIME_WAIT需要等待2MSL,當(dāng)TCP的一端發(fā)起主動關(guān)閉,三次揮手完成后發(fā)送第四次揮手的ACK包后就進入這個狀態(tài),等待2MSL時間主要目的是:防止最后一個ACK包對方?jīng)]有收到,那么對方在超時后將重發(fā)第三次揮手的FIN包,主動關(guān)閉端接到重發(fā)的FIN包后可以再發(fā)一個ACK應(yīng)答包。在TIME_WAIT狀態(tài)時兩端的端口不能使用,要等到2MSL時間結(jié)束才可以繼續(xù)使用。當(dāng)連接處于2MSL等待階段時任何遲到的報文段都將被丟棄。
2.client發(fā)送完最后一個ack之后,進入time_wait狀態(tài),但是他怎么知道server有沒有收到這個ack呢?莫非sever也要等待一段時間,如果收到了這個ack就close,如果沒有收到就再發(fā)一個fin給client?這么說server最后也有一個time_wait哦?求解答!
因為網(wǎng)絡(luò)原因,主動關(guān)閉的一方發(fā)送的這個ACK包很可能延遲,從而觸發(fā)被動連接一方重傳FIN包。極端情況下,這一去一回,就是兩倍的MSL時長。如果主動關(guān)閉的一方跳過TIME_WAIT直接進入CLOSED,或者在TIME_WAIT停留的時長不足兩倍的MSL,那么當(dāng)被動關(guān)閉的一方早先發(fā)出的延遲包到達后,就可能出現(xiàn)類似下面的問題:1.舊的TCP連接已經(jīng)不存在了,系統(tǒng)此時只能返回RST包2.新的TCP連接被建立起來了,延遲包可能干擾新的連接,這就是為什么time_wait需要等待2MSL時長的原因。
3.為什么連接的時候是三次握手,關(guān)閉的時候卻是四次握手?
因為當(dāng)Server端收到Client端的SYN連接請求報文后,可以直接發(fā)送SYN+ACK報文。其中ACK報文是用來應(yīng)答的,SYN報文是用來同步的。但是關(guān)閉連接時,當(dāng)Server端收到FIN報文時,很可能并不會立即關(guān)閉SOCKET,所以只能先回復(fù)一個ACK報文,告訴Client端,"你發(fā)的FIN報文我收到了"。只有等到我Server端所有的報文都發(fā)送完了,我才能發(fā)送FIN報文,因此不能一起發(fā)送。故需要四步握手。