TCP協(xié)議
TCP協(xié)議耙替,即傳輸控制協(xié)議
(英文全拼:Transmission Control Protocol)陆爽。 其是一種面向連接的、可靠的软能、基于字節(jié)流的傳輸層通信協(xié)議挠羔。 TCP通信
需要經(jīng)過創(chuàng)建連接
、傳送數(shù)據(jù)
埋嵌、終止連接
三個(gè)步驟。在通信傳輸之前俱恶,先要打開一個(gè)連接雹嗦,連接關(guān)閉后無法再發(fā)送數(shù)據(jù)。
TCP通信類似生活中的“打電話”合是,打電話之前了罪,必須要先撥打?qū)Ψ降碾娫捥柎a請求建立連接,接通后雙方才能通信聪全,而電話掛斷后就不能再進(jìn)行通信了泊藕。
TCP特點(diǎn)
1.面向連接
進(jìn)行TCP通信的雙方必須先建立連接,然后才能進(jìn)行數(shù)據(jù)的傳輸难礼,雙方都必須為該連接分配必要的系統(tǒng)內(nèi)核資源娃圆,以管理連接的狀態(tài)和連接上的傳輸。 雙方間的數(shù)據(jù)傳輸都在這一個(gè)連接上進(jìn)行蛾茉。完成數(shù)據(jù)交換后讼呢,雙方必須斷開此連接,以釋放系統(tǒng)資源谦炬。并且這種連接是一對一的悦屏。
2.可靠傳輸
TCP通過4種機(jī)制實(shí)現(xiàn)可靠傳輸:
1)TCP采用發(fā)送應(yīng)答機(jī)制
TCP發(fā)送的每個(gè)報(bào)文段都必須得到接收方的應(yīng)答,如此才會認(rèn)為這個(gè)TCP報(bào)文段傳輸成功键思。
2)超時(shí)重傳
發(fā)送端發(fā)出一個(gè)報(bào)文段之后就啟動定時(shí)器础爬,如果在定時(shí)時(shí)間內(nèi)沒有收到應(yīng)答就重新發(fā)送這個(gè)報(bào)文段。
TCP為了保證不發(fā)生丟包吼鳞,就給每個(gè)包一個(gè)序號看蚜,序號也保證了傳送到接收端實(shí)體的包的按序接收。然后接收端實(shí)體對已成功收到的包發(fā)回一個(gè)相應(yīng)的確認(rèn)(ACK)赖条。如果發(fā)送端實(shí)體在合理的往返時(shí)延(RTT)內(nèi)未收到確認(rèn)失乾,那么就會假設(shè)對應(yīng)的數(shù)據(jù)包已丟失將會進(jìn)行重傳常熙。
3)錯(cuò)誤校驗(yàn)
TCP用一個(gè)校驗(yàn)和函數(shù)來檢驗(yàn)數(shù)據(jù)是否有錯(cuò)誤,在發(fā)送和接收時(shí)都要計(jì)算校驗(yàn)和碱茁。
4)流量控制和阻塞管理
流量控制用來避免主機(jī)發(fā)送得過快而使接收方來不及完全收下裸卫。
3.基于字節(jié)流
TCP是一種流模式協(xié)議(steam protocol),數(shù)據(jù)是以字節(jié)流的形式進(jìn)行傳輸?shù)呐ⅲ渲袀魉偷淖止?jié)流中的每個(gè)字節(jié)都按順序編號墓贿。
TCP發(fā)送字節(jié)流數(shù)據(jù)流程:
(1)先將某次發(fā)送的數(shù)據(jù)作為一個(gè)數(shù)據(jù)塊暫存到發(fā)送緩存區(qū),發(fā)送時(shí)在緩存區(qū)先后打包成TCP報(bào)文段和IP數(shù)據(jù)包后發(fā)送(由于緩存區(qū)不止存在此次發(fā)送的數(shù)據(jù)蜓氨,一個(gè)數(shù)據(jù)塊可能會被分割成一部分與其他數(shù)據(jù)塊一同被打包成TCP報(bào)文段)聋袋;
(2)TCP報(bào)文段包含TCP首部
和TCP數(shù)據(jù)
兩部分,首部包含源端口號
和目的端口號
穴吹、字節(jié)序號及確認(rèn)號等信息幽勒;該TCP報(bào)文段被進(jìn)一步包裝,成為IP報(bào)文段港令,包含IP首部
和IP數(shù)據(jù)部分
啥容,IP首部包含源IP地址
和目的IP地址
等信息,IP數(shù)據(jù)部分即是TCP報(bào)文段顷霹;
(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é)在兩臺計(jì)算機(jī)之間建立可靠連接袍辞,保證數(shù)據(jù)包按順序到達(dá)徽缚。
建立TCP連接-3次握手
建立一個(gè)TCP連接時(shí),需要客戶端和服務(wù)端進(jìn)行“3次握手”革屠,以確認(rèn)建立連接凿试。“3次握手”是對客戶端和服務(wù)端通過發(fā)3個(gè)包來確認(rèn)建立連接的比喻似芝。
3次握手
的流程如下圖所示:
(1)第一次握手:Client將標(biāo)志位SYN置為1那婉,隨機(jī)產(chǎn)生一個(gè)值seq=J,并將該數(shù)據(jù)包發(fā)送給Server党瓮,Client進(jìn)入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在跳,隨機(jī)產(chǎn)生一個(gè)值seq=K,并將該數(shù)據(jù)包發(fā)送給Client以確認(rèn)連接請求隐岛,Server進(jìn)入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進(jìn)入ESTABLISHED狀態(tài),完成三次握手摩瞎,隨后Client與Server之間可以開始傳輸數(shù)據(jù)了蔫饰。
為何非要3次握手?
一次愉豺、兩次握手建立連接的不可行性:
1)一次握手建立連接,即客戶端發(fā)送一個(gè)請求連接的數(shù)據(jù)包即建立連接:由于TCP協(xié)議的接收應(yīng)答機(jī)制茫因,一次握手肯定不行蚪拦,一方面服務(wù)端可能沒有接收到這個(gè)請求,另一方面客戶端也無法知曉服務(wù)端是否接收到了這個(gè)請求冻押;在這種情形下建立的連接非常不可靠驰贷,可能只是客戶端單方面的分配連接資源,而服務(wù)端完全不知道情形洛巢;
2)兩次握手建立連接括袒,即客戶端和服務(wù)端各發(fā)送一個(gè)數(shù)據(jù)包即建立連接:第一次握手是客戶端請求建立連接,第二次握手是服務(wù)端響應(yīng)連接請求稿茉,然后服務(wù)端即分配資源建立連接锹锰。但是服務(wù)端的響應(yīng)連接請求的信號客戶端可能沒有接收到,由于TCP協(xié)議的接收應(yīng)答機(jī)制漓库,客戶端會再次發(fā)出建立連接的請求恃慧,這樣服務(wù)端又會再次分配資源建立連接,而前一次連接就會是占系統(tǒng)用資源的無效連接渺蒿。假設(shè)服務(wù)端每次發(fā)送的數(shù)據(jù)一直在丟失痢士,客戶端一直SYN,服務(wù)器就會產(chǎn)生多個(gè)無效連接茂装,占用資源怠蹂,這個(gè)時(shí)候服務(wù)器可能會掛掉善延。這個(gè)現(xiàn)象就是我們聽過的“SYN的洪水攻擊”。
三次握手建立連接的可行性:
第一次握手是客戶端發(fā)起建立連接的請求城侧,然后服務(wù)端響應(yīng)此請求表示可以建立連接進(jìn)行了第二次握手易遣,最后第三次握手是客戶端對服務(wù)端表示可以建立連接的再次響應(yīng),代表客戶端接收到了服務(wù)端發(fā)出的可以連接的信號赞庶。這之后雙方都能確認(rèn)對方接收到了自己的信號训挡,因此可以開始分配資源建立連接傳輸數(shù)據(jù)。三次握手能夠建立可靠的連接歧强。
四次澜薄、五次握手的不必要性: 由于三次握手即可以創(chuàng)建可靠的連接了,四次摊册、五次握手就沒有必要了肤京。
形象一點(diǎn)TCP三次握手就像我們打電話,第一方會先“喂茅特,聽得到我說話嗎忘分?”,另一方“嗯白修,聽到了妒峦,你聽得到我說話嗎?”兵睛,第一方又說“也聽得到”肯骇,雙方都確認(rèn)對方能聽到自己說話后才開始真正的交流。斷開TCP連接-4次揮手
斷開客戶端和服務(wù)器的TCP連接需要經(jīng)過“四次揮手”祖很。
第一次揮手:主機(jī)1(可以是客戶端笛丙,也可以是服務(wù)器端),設(shè)置Sequence Number
和Acknowledgment Number
假颇,向主機(jī)2發(fā)送一個(gè)FIN
報(bào)文段胚鸯;此時(shí),主機(jī)1進(jìn)入FIN_WAIT_1
狀態(tài)笨鸡;這表示主機(jī)1沒有數(shù)據(jù)要發(fā)送給主機(jī)2了姜钳;
第二次揮手:主機(jī)2收到了主機(jī)1發(fā)送的FIN
報(bào)文段,向主機(jī)1回一個(gè)ACK
報(bào)文段形耗,Acknowledgment Number
為Sequence Number
加1傲须;主機(jī)1進(jìn)入FIN_WAIT_2
狀態(tài);
第三次揮手:主機(jī)2向主機(jī)1發(fā)送FIN
報(bào)文段趟脂,請求關(guān)閉連接泰讽,同時(shí)主機(jī)2進(jìn)入CLOSE_WAIT
狀態(tài);這表示主機(jī)2告訴主機(jī)1,我也沒有數(shù)據(jù)要發(fā)送了已卸,可以進(jìn)行關(guān)閉連接了佛玄;
第四次揮手:主機(jī)1收到主機(jī)2發(fā)送的FIN
報(bào)文段,向主機(jī)2發(fā)送ACK
報(bào)文段累澡,然后主機(jī)1進(jìn)入TIME_WAIT
狀態(tài)梦抢;主機(jī)2收到主機(jī)1的ACK
報(bào)文段以后,就關(guān)閉連接愧哟;此時(shí)奥吩,主機(jī)1等待2MSL后依然沒有收到回復(fù),則證明Server端已正常關(guān)閉蕊梧,那好霞赫,主機(jī)1也可以關(guān)閉連接了。
問題
1.為什么TIME_WAIT狀態(tài)需要經(jīng)過2MSL(最大報(bào)文段生存時(shí)間)才能返回到CLOSE狀態(tài)肥矢?
首先端衰,MSL即Maximum Segment Lifetime,就是最大報(bào)文生存時(shí)間甘改,是任何報(bào)文在網(wǎng)絡(luò)上的存在的最長時(shí)間旅东,超過這個(gè)時(shí)間報(bào)文將被丟棄∈《TCP/IP詳解》中是這樣描述的:MSL是任何報(bào)文段被丟棄前在網(wǎng)絡(luò)內(nèi)的最長時(shí)間抵代。RFC 793中規(guī)定MSL為2分鐘,實(shí)際應(yīng)用中常用的是30秒忘嫉、1分鐘荤牍、2分鐘等。
TCP的TIME_WAIT需要等待2MSL榄融,當(dāng)TCP的一端發(fā)起主動關(guān)閉,三次揮手完成后發(fā)送第四次揮手的ACK包后就進(jìn)入這個(gè)狀態(tài)救湖,等待2MSL時(shí)間主要目的是:防止最后一個(gè)ACK包對方?jīng)]有收到愧杯,那么對方在超時(shí)后將重發(fā)第三次揮手的FIN包,主動關(guān)閉端接到重發(fā)的FIN包后可以再發(fā)一個(gè)ACK應(yīng)答包鞋既。在TIME_WAIT狀態(tài)時(shí)兩端的端口不能使用力九,要等到2MSL時(shí)間結(jié)束才可以繼續(xù)使用。當(dāng)連接處于2MSL等待階段時(shí)任何遲到的報(bào)文段都將被丟棄邑闺。
2.client發(fā)送完最后一個(gè)ack之后跌前,進(jìn)入time_wait狀態(tài),但是他怎么知道server有沒有收到這個(gè)ack呢陡舅?莫非sever也要等待一段時(shí)間抵乓,如果收到了這個(gè)ack就close,如果沒有收到就再發(fā)一個(gè)fin給client?這么說server最后也有一個(gè)time_wait哦灾炭?求解答茎芋!
因?yàn)榫W(wǎng)絡(luò)原因,主動關(guān)閉的一方發(fā)送的這個(gè)ACK包很可能延遲蜈出,從而觸發(fā)被動連接一方重傳FIN包田弥。極端情況下,這一去一回铡原,就是兩倍的MSL時(shí)長偷厦。如果主動關(guān)閉的一方跳過TIME_WAIT直接進(jìn)入CLOSED,或者在TIME_WAIT停留的時(shí)長不足兩倍的MSL燕刻,那么當(dāng)被動關(guān)閉的一方早先發(fā)出的延遲包到達(dá)后只泼,就可能出現(xiàn)類似下面的問題:1.舊的TCP連接已經(jīng)不存在了,系統(tǒng)此時(shí)只能返回RST包2.新的TCP連接被建立起來了酌儒,延遲包可能干擾新的連接辜妓,這就是為什么time_wait需要等待2MSL時(shí)長的原因。
3.為什么連接的時(shí)候是三次握手忌怎,關(guān)閉的時(shí)候卻是四次握手籍滴?
因?yàn)楫?dāng)Server端收到Client端的SYN連接請求報(bào)文后,可以直接發(fā)送SYN+ACK報(bào)文榴啸。其中ACK報(bào)文是用來應(yīng)答的孽惰,SYN報(bào)文是用來同步的。但是關(guān)閉連接時(shí)鸥印,當(dāng)Server端收到FIN報(bào)文時(shí)勋功,很可能并不會立即關(guān)閉SOCKET,所以只能先回復(fù)一個(gè)ACK報(bào)文库说,告訴Client端狂鞋,"你發(fā)的FIN報(bào)文我收到了"。只有等到我Server端所有的報(bào)文都發(fā)送完了潜的,我才能發(fā)送FIN報(bào)文骚揍,因此不能一起發(fā)送。故需要四步握手啰挪。