面向連接的運(yùn)輸:TCP
TCP連接
TCP被稱為面向連接的,因?yàn)樵趹?yīng)用程序開始互傳數(shù)據(jù)之前,TCP會(huì)先建立一個(gè)連接,該連接的建立涉及到三次“握手”。
TCP的連接不是一條真實(shí)存在的電路,而是一條邏輯鏈接,其共同狀態(tài)僅保留在兩個(gè)通信端系統(tǒng)的TCP程序中。
TCP連接也是點(diǎn)對(duì)點(diǎn)的,即TCP連接只能存在于一對(duì)一對(duì)的主機(jī)之間,不允許多于兩臺(tái)主機(jī)的共同建立一條TCP連接,最大主機(jī)數(shù)量為兩臺(tái)。
三次握手的簡(jiǎn)述
1.客戶首先發(fā)送一個(gè)特殊的TCP報(bào)文段。
2.服務(wù)器用另一個(gè)特殊的TCP報(bào)文段來響應(yīng)。
3.最后,客戶用第三個(gè)特殊報(bào)文段作為響應(yīng)。
前兩個(gè)報(bào)文段不承載“有效載荷”,即不包含應(yīng)用層數(shù)據(jù)。而第三個(gè)報(bào)文段可以承載有效載荷。
這個(gè)過程被稱為三次握手。
TCP連接的組成
客戶進(jìn)程通過套接字傳遞數(shù)據(jù)流,數(shù)據(jù)一旦通過該門,它就由客戶中的TCP控制,TCP將這些數(shù)據(jù)引導(dǎo)到該連接的發(fā)送緩存里。
發(fā)送緩存是三次握手期間設(shè)置的緩存之一。
隨后TCP將不時(shí)地從緩存里取出一塊數(shù)據(jù),并將數(shù)據(jù)傳遞給網(wǎng)絡(luò)層,并且發(fā)送給接收方。
TCP從緩存中取出并放入報(bào)文段的數(shù)據(jù)數(shù)量受限于最大報(bào)文段長度(MSS)。
MSS通常由本地發(fā)送主機(jī)發(fā)送的最大鏈路層幀長度(即最大傳輸單元MTU)來設(shè)置。
TCP在接收端接收到一個(gè)報(bào)文段后,會(huì)將該報(bào)文段存入接收緩存中,應(yīng)用程序則從接收緩存中取得數(shù)據(jù)。
TCP連接的組成包括:一臺(tái)主機(jī)上的發(fā)送緩存、套接字、變量,另一臺(tái)主機(jī)上的接收緩存、套接字、變量。
TCP報(bào)文段結(jié)構(gòu)
TCP報(bào)文段主要包含下列字段:
1.32比特的序號(hào)字段、32比特的確認(rèn)號(hào)字段。
2.16比特的接收窗口字段,用來流量控制。
3.4比特的首部長度字段,用來標(biāo)識(shí)TCP首部長度。
4.可選與變長的選項(xiàng)字段,用于發(fā)送方與接收方協(xié)商最大報(bào)文長度(MSS)時(shí)。
5.6比特的標(biāo)志字段。
序號(hào)和確認(rèn)號(hào)
TCP對(duì)序號(hào)的使用建立在傳送的字節(jié)流上嗎,并不建立在傳送的報(bào)文段序列之上,一個(gè)報(bào)文段的序號(hào)是該報(bào)文段首字母的序號(hào)。
例如下面?zhèn)魉鸵粋€(gè)500 000字節(jié)的文件,其MSS為1000字節(jié),數(shù)據(jù)流的首字節(jié)編號(hào)是0.
則下圖標(biāo)識(shí)了文件數(shù)據(jù)被換分成不同TCP報(bào)文段的方式:
TCP的累積確認(rèn)
現(xiàn)在假設(shè)主機(jī)A收到了主機(jī)B的字節(jié)0~535的報(bào)文段,以及另一個(gè)包含字節(jié)900~1000的報(bào)文段。
但沒有收到536~899的報(bào)文段。所以主機(jī)A為了重新構(gòu)建主機(jī)B的數(shù)據(jù)流,仍在等待字節(jié)536(和其
后的字節(jié))。因此,A到B的下一個(gè)報(bào)文段將在確認(rèn)號(hào)字段中包含536.
因?yàn)門CP只確認(rèn)該流中第一個(gè)字節(jié),所以TCP被稱為提供累積確認(rèn)。
下面是Telnet:序號(hào)和確認(rèn)號(hào)的一個(gè)典型示意圖:
往返時(shí)間的估計(jì)與超時(shí)
因?yàn)門CP需要實(shí)現(xiàn)超時(shí)/重傳機(jī)制,但是超時(shí)的時(shí)間該怎么設(shè)置呢?重傳的時(shí)間又該設(shè)置為多少呢?
為此需要根據(jù)往返時(shí)間來測(cè)定這個(gè)超時(shí)的時(shí)間,但是往返時(shí)間的動(dòng)態(tài)測(cè)定顯然是不現(xiàn)實(shí)的,為此我們可以估計(jì)往返時(shí)間。
估計(jì)往返時(shí)間
估計(jì)往返時(shí)間由如下方法來完成:
1.報(bào)文段的樣本RTT(SampleRTT)就是從某報(bào)文段被發(fā)出到該報(bào)文段被接收之間的時(shí)間量。
大多數(shù)TCP的實(shí)現(xiàn)僅在某個(gè)時(shí)刻做一次SampleRTT測(cè)量。
然后對(duì)于SampleRTT的值也許都是非典型的,因此我們引入了一個(gè)典型的值,叫做
EstimatedRTT,也就是動(dòng)態(tài)的RTT。
它使用如下公式獲得:
EstimatedRTT是一個(gè)SampleRTT的加權(quán)平均值。
從統(tǒng)計(jì)學(xué)觀點(diǎn)講,這種平均被稱為指數(shù)加權(quán)移動(dòng)平均(EWMA)。
下圖是一個(gè)SampleRTT和EstimatedRTT的例子:
除了估算RTT以外,我們還可以測(cè)量RTT的變化,也就是RTT偏差DevRTT:
DevRTT是一個(gè)SampleRTT與Estimated之間差值的EWMA,如果SampleRTT值波動(dòng)較小,那么DevRTT的值就會(huì)很小,如果波動(dòng)很大,那么DevRTT的值就會(huì)很大。
設(shè)置和管理重傳超時(shí)間隔
TCP超時(shí)間隔應(yīng)該大于等于EstimatedRTT,否則將會(huì)造成不必要的重傳,但是也不應(yīng)該比EstimatedRTT大太多。
TimeoutInterval = EstimatedRTT + 4·DevRTT
可靠數(shù)據(jù)傳輸
因?yàn)?strong>IP是不可靠的,所以TCP在IP之上創(chuàng)建了一種可靠數(shù)據(jù)傳輸服務(wù)。
在TCP上傳輸?shù)膱?bào)文段,通過一個(gè)定時(shí)器來管理,通過這種管理方法,TCP實(shí)現(xiàn)了可靠數(shù)據(jù)傳輸。
下面是一個(gè)TCP發(fā)送方高度簡(jiǎn)化的模型:
關(guān)于以上的模型,TCP必須相應(yīng)三個(gè)主要事件:
1.當(dāng)上層應(yīng)用傳送數(shù)據(jù)到TCP時(shí),TCP通過將上層應(yīng)用數(shù)據(jù)打包成報(bào)文段并且轉(zhuǎn)移到TCP發(fā)送緩存中。
2.超時(shí)。即TCP通過重傳引起超時(shí)的報(bào)文段來響應(yīng)超時(shí)事件。
3.收到一個(gè)來自接收方的確認(rèn)報(bào)文段(ACK包含的一個(gè)有效ACK字段值),TCP將這個(gè)值y個(gè)變量
SendBase進(jìn)行比較。因?yàn)镾endBase時(shí)最早未被確認(rèn)的字節(jié)的序號(hào),因此SendBase是最后一個(gè)已
經(jīng)被確認(rèn)的字節(jié)的序號(hào),TCP采用累積確認(rèn),所以一旦y大于SendBase說明ACK是在確認(rèn)或多個(gè)
報(bào)文段。因此需要更新SendBase的值。
流量控制
TCP將發(fā)送方的數(shù)據(jù)傳送給接收方緩存,而應(yīng)用程序中則從該緩存中讀取數(shù)據(jù),并不是數(shù)據(jù)一到達(dá)
立馬讀取。但如果程序很久沒有讀取數(shù)據(jù),那么緩存可能會(huì)被很多數(shù)據(jù)所撐爆,造成數(shù)據(jù)溢出。
因此TCP為它的應(yīng)用程序提供了流量控制服務(wù)。
流量控制是一個(gè)速度匹配服務(wù),即發(fā)送方和接收方應(yīng)用程序的讀取速率相匹配。
流量控制的實(shí)現(xiàn)
TCP通過讓發(fā)送方維護(hù)一個(gè)稱為接收窗口的變量來提供流量控制。該窗口用于給發(fā)送方一個(gè)提示,
即接收方還有多少可用的緩存空間。
下面我們定義兩個(gè)變量:
LastByteRead:主機(jī)B上的應(yīng)用進(jìn)程從緩存中讀出的數(shù)據(jù)流的最后一個(gè)字節(jié)的編號(hào)。
LastByteRcvd:從網(wǎng)絡(luò)中達(dá)到B接收緩存中的數(shù)據(jù)流的最后一個(gè)字節(jié)編號(hào)。
因此,我們給出下面式子必須成立:
LastByteRcvd - LastByteRead <= RcvBuffer(接收緩存)
而接收窗口用rwnd標(biāo)識(shí),根據(jù)接收緩存可用空間的數(shù)量來設(shè)置:
rwnd = RcvBuffer - [LastByteRcvd - LastByteRead]
注意到空間是隨著時(shí)間變化的,所以rwnd也是動(dòng)態(tài)的。
下圖也是一個(gè)對(duì)于rwnd的一個(gè)圖示:
而接受主機(jī)B則將rwnd放入確認(rèn)報(bào)文段發(fā)送給A,從而通知A在該連接的緩存中還有多少可用空間。
特別注意,發(fā)送方在接收方的接收窗口也就是rwnd為0時(shí),發(fā)送方會(huì)繼續(xù)發(fā)送一個(gè)只有一個(gè)字節(jié)數(shù)
據(jù)的報(bào)文段。這些報(bào)文段會(huì)被接收方確認(rèn),最終緩存將開始清空,并且此時(shí)返回的確認(rèn)報(bào)文段是一
個(gè)非0的rwnd值。
(如果不這樣做,在發(fā)送方接收到rwnd為0,也就是接收窗口已經(jīng)滿了,因此發(fā)送方會(huì)被堵塞,但
是因?yàn)榘l(fā)送方不發(fā)送一個(gè)報(bào)文段,接收方也不會(huì)發(fā)送一個(gè)確認(rèn)報(bào)文段包含rwnd。所以此時(shí)發(fā)送方
不知道接收方的rwnd是否已經(jīng)被清空了,也就是緩存中的數(shù)據(jù)是否已經(jīng)被應(yīng)用程序取走部分,或
者全部取走了。)
TCP連接管理
下面我們來特別仔細(xì)地觀察一下如何建立和拆除一條TCP連接,涉及到三次握手。
下面我們假設(shè)一個(gè)客戶的進(jìn)程想要與服務(wù)器上的一個(gè)進(jìn)程建立一個(gè)連接,則TCP會(huì)用以下方式來與
服務(wù)器TCP建立連接:
1.客戶端的TCP首先向服務(wù)器端的的TCP發(fā)送一個(gè)特殊的TCP報(bào)文段。該報(bào)文段不包含應(yīng)用層數(shù)
據(jù)。但是在報(bào)文段的首部中的一個(gè)標(biāo)志位(SYN比特標(biāo)志位)被置為1。所以這個(gè)報(bào)文段也被稱為
SYN報(bào)文段。
同時(shí),客戶會(huì)隨機(jī)選擇一個(gè)初始序號(hào),并將此編號(hào)放置于該起始的TCP SYN報(bào)文段的序號(hào)字段
中,該報(bào)文段會(huì)被封裝在一個(gè)IP數(shù)據(jù)包中發(fā)送給服務(wù)器。
2.當(dāng)服務(wù)器接收到數(shù)據(jù)報(bào)后,會(huì)從中提取出TCP SYN報(bào)文段,并且為該TCP連接分配TCP緩存和
變量,并向客戶TCP發(fā)送允許連接的報(bào)文段。這個(gè)允許連接的報(bào)文段也不包含應(yīng)用層數(shù)據(jù)。但在
報(bào)文段首部包含三個(gè)重要信息。
首先,SYN比特被置為1。
其次,該TCP報(bào)文段的首部被指為client_isn + 1。
最后,服務(wù)器選擇自己的初始序號(hào)(server_isn)并且將它放進(jìn)TCP報(bào)文段的序號(hào)字段中。
這一個(gè)允許連接的報(bào)文段通俗點(diǎn)來說就是:
“我收到了你發(fā)起連接的SYN分組,該分組帶有初始序號(hào)client_isn。我同意建立該連接,我的初始
序號(hào)為server_isn”,該報(bào)文段也被稱為SYNACK報(bào)文段。
3.在接收到SYNACK報(bào)文段后,客戶也要給該連接分配緩存和變量,客戶機(jī)向服務(wù)器發(fā)送另外一個(gè)
報(bào)文段,該報(bào)文段也是最后一個(gè)報(bào)文段,對(duì)服務(wù)器允許連接的報(bào)文段進(jìn)行一次確認(rèn)。
(通過將server_isn + 1放置到TCP報(bào)文段首部的確認(rèn)字段中來完成此項(xiàng)工作)。
此時(shí)連接已經(jīng)建立了,所以該報(bào)文段的SYN比特被置為0。
該報(bào)文段可以攜帶客戶到服務(wù)器的數(shù)據(jù)。
一旦完成這三個(gè)步驟,客戶和服務(wù)器就可以相互發(fā)送數(shù)據(jù)報(bào)文段了,并且此后的所有報(bào)文段的SYN
比特都會(huì)是0.
下面是一個(gè)TCP三次握手報(bào)文段交換的例子圖:
而對(duì)于TCP連接的中斷,客戶機(jī)的進(jìn)程和服務(wù)器的進(jìn)程任何一個(gè)進(jìn)程都可以終止該連接,當(dāng)連接終
止后,主機(jī)中的“資源”(變量和緩存)將會(huì)被釋放。
例如,當(dāng)客戶想要關(guān)閉一個(gè)TCP連接,那么應(yīng)用程序對(duì)TCP發(fā)出一個(gè)關(guān)閉連接的命令,TCP接收到
命令后,對(duì)服務(wù)器發(fā)送一個(gè)特殊的TCP報(bào)文段。
該報(bào)文段的首部FIN比特標(biāo)志位被置為1,用于表示需要關(guān)閉TCP連接。
而服務(wù)器TCP接收到這個(gè)報(bào)文段后,就向客戶發(fā)送一個(gè)確認(rèn)關(guān)閉的報(bào)文段。
在經(jīng)過一小段時(shí)間后,服務(wù)器再向客戶發(fā)送一個(gè)關(guān)閉報(bào)文段,這個(gè)關(guān)閉報(bào)文段的FIN比特標(biāo)志位也
是1。
最后客戶對(duì)服務(wù)器的關(guān)閉報(bào)文段進(jìn)行回應(yīng),此時(shí)兩臺(tái)主機(jī)上的資源就都釋放了。
下圖是該過程的一個(gè)示例圖:
下圖是一個(gè)客戶TCP在建立連接->傳送數(shù)據(jù)->關(guān)閉連接所有的狀態(tài)圖:
下面來考慮一下,當(dāng)一臺(tái)主機(jī)接收到一個(gè)TCP報(bào)文段,該報(bào)文段的源IP或端口號(hào)并不與主機(jī)的套接
字相匹配。
因此,該主機(jī)將發(fā)送一個(gè)特殊重置報(bào)文段。該報(bào)文段將受不得RST比特標(biāo)志位置為1.文章來源:http://www.zghlxwxcb.cn/news/detail-720258.html
告訴源:“我沒有那個(gè)報(bào)文段的套接字,請(qǐng)不要再發(fā)送該報(bào)文段了?!?span toymoban-style="hidden">文章來源地址http://www.zghlxwxcb.cn/news/detail-720258.html
到了這里,關(guān)于計(jì)算機(jī)網(wǎng)絡(luò)-TCP協(xié)議的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!