本篇文章較長(zhǎng),大家先看下目錄
1、簡(jiǎn)介
2、TCP協(xié)議頭
3、TCP數(shù)據(jù)包的編號(hào)(SEQ)
4、三次握手建立連接
5、四次揮手?jǐn)嚅_連接
6、TCP可靠性的保證
7、滑動(dòng)窗口技術(shù)
9、窗口滑動(dòng)的數(shù)據(jù)重發(fā)
9、TCP流控制
10、網(wǎng)線“斷”了怎么辦
01 簡(jiǎn)介
TCP(Transmission Control Protocol 傳輸控制協(xié)議)是一種基于IP的傳輸層協(xié)議,TCP協(xié)議面向連接、正面確認(rèn)與重傳、緩沖機(jī)制、流量控制、差錯(cuò)控制、擁塞控制,可保證高可靠性(數(shù)據(jù)無(wú)丟失、數(shù)據(jù)無(wú)失序、數(shù)據(jù)無(wú)錯(cuò)誤、數(shù)據(jù)無(wú)重復(fù)到達(dá))傳輸層協(xié)議。
上圖形象展示了TCP協(xié)議是基于IP協(xié)議的傳輸層協(xié)議,對(duì)于IP協(xié)議的詳解,請(qǐng)看《IP協(xié)議詳解》。
02 TCP協(xié)議頭
TCP協(xié)議頭數(shù)據(jù)個(gè)數(shù)如下:
端口號(hào)[16bit]
我們知道,網(wǎng)絡(luò)實(shí)現(xiàn)的是不同主機(jī)的進(jìn)程間通信。在一個(gè)操作系統(tǒng)中,有很多進(jìn)程,當(dāng)數(shù)據(jù)到來(lái)時(shí)要提交給哪個(gè)進(jìn)程進(jìn)行處理呢?這就需要用到端口號(hào)。在TCP頭中,有源端口號(hào)(SourcePort)和目標(biāo)端口號(hào)(DestinationPort)。源端口號(hào)標(biāo)識(shí)了發(fā)送主機(jī)的進(jìn)程,目標(biāo)端口號(hào)標(biāo)識(shí)接受方主機(jī)的進(jìn)程。端口是由互聯(lián)網(wǎng)分配號(hào)碼管理局(IANA)分配的,具體請(qǐng)看《UDP協(xié)議詳解》。
序號(hào)[32bit]
序號(hào)分為發(fā)送序號(hào)(SequenceNumber)和確認(rèn)序號(hào)(AcknowledgmentNumber)。
發(fā)送序號(hào):用來(lái)標(biāo)識(shí)從TCP源端向TCP目的端發(fā)送的數(shù)據(jù)字節(jié)流,它表示在這個(gè)報(bào)文段中的第一個(gè)數(shù)據(jù)字節(jié)的順序號(hào)。如果將字節(jié)流看作在兩個(gè)應(yīng)用程序間的單向流動(dòng),則TCP用順序號(hào)對(duì)每個(gè)字節(jié)進(jìn)行計(jì)數(shù)。序號(hào)是32bit的無(wú)符號(hào)數(shù),序號(hào)到達(dá)2∧32-1后又從0開始。當(dāng)建立一個(gè)新的連接時(shí),SYN標(biāo)志變1,順序號(hào)字段包含由這個(gè)主機(jī)選擇的該連接的初始順序號(hào)ISN(Initial Sequence Number)。
確認(rèn)序號(hào):包含發(fā)送確認(rèn)的一端所期望收到的下一個(gè)順序號(hào)。因此,確認(rèn)序號(hào)應(yīng)當(dāng)是上次已成功收到數(shù)據(jù)字節(jié)順序號(hào)加1。只有ACK標(biāo)志為1時(shí)確認(rèn)序號(hào)字段才有效。TCP為應(yīng)用層提供全雙工服務(wù),這意味數(shù)據(jù)能在兩個(gè)方向上獨(dú)立地進(jìn)行傳輸。因此,連接的每一端必須保持每個(gè)方向上的傳輸數(shù)據(jù)順序號(hào)。
在wireshark的抓包文件中,Seq表示發(fā)送序列號(hào),Ack表示確認(rèn)序列號(hào)。
偏移[4bit]
這里的偏移實(shí)際指的是TCP首部的長(zhǎng)度,它用來(lái)表明TCP首部中32bit字的數(shù)目,通過(guò)它可以知道一個(gè)TCP包它的用戶數(shù)據(jù)是從哪里開始的。這個(gè)字段占4bit,如4bit的值是0101,則說(shuō)明TCP首部長(zhǎng)度是5* 4 = 20字節(jié)。所以TCP的首部長(zhǎng)度最大為15* 4 = 60字節(jié)。然而沒有可選字段,正常長(zhǎng)度為20字節(jié)。
Reserved [3bit]
目前沒有使用,它的值都為0。注意:在比較舊的資料中顯示6bit的保留字節(jié),因?yàn)樾碌腡CP協(xié)議使用了3個(gè)位作為標(biāo)志,所以只剩下3個(gè)保留位。
標(biāo)志[9bit]
上面說(shuō)到增加了3位作標(biāo)志位,增加的是:
NS: "nonce sum"簡(jiǎn)寫。隨機(jī)和,該標(biāo)簽用來(lái)保護(hù)不受發(fā)送者發(fā)送的突發(fā)的惡意隱藏報(bào)文的侵害。
CWR: "Congestion WindowReduced"簡(jiǎn)寫。擁塞窗口減,發(fā)送方降低它的發(fā)送速率,發(fā)送者在接收到一個(gè)帶有ECEflag包時(shí),將會(huì)使用CWRflag。
ECE: "ECN-Echo"簡(jiǎn)寫。ECN表示ExplicitCongestion Notification(顯式擁塞通知),發(fā)送方接收到了一個(gè)更早的擁塞通告。表示TCPpeer有ECN能力。
其他6個(gè)標(biāo)志位
URG: "urgent"簡(jiǎn)寫。通知接收端處理在處理其他包前優(yōu)先處理接收到的緊急報(bào)文(urgentpackets),緊急指針(urgentpointer)有效。
ACK: "Acknowledgment"簡(jiǎn)寫。表示包已經(jīng)被成功接收,確認(rèn)序號(hào)有效。
PSH: "push"簡(jiǎn)寫。通知接收端處理接收的報(bào)文,而不是將報(bào)文緩存到buffer中。
RST:"reset"簡(jiǎn)寫。重置連接標(biāo)志,用于重置由于主機(jī)崩潰或其他原因而出現(xiàn)錯(cuò)誤的連接。復(fù)位通訊請(qǐng)求,一般表示斷開一個(gè)連接。我們把含有RST標(biāo)識(shí)的報(bào)文稱為復(fù)位報(bào)文段。
SYN:"Synchronisation"簡(jiǎn)寫。表示三次握手建立連接的第一步,在建立連接時(shí)發(fā)送者發(fā)送的第一個(gè)包中設(shè)置flag值為SYN。我們把含有SYN標(biāo)識(shí)的報(bào)文稱為同步報(bào)文段。
FIN: "finished"簡(jiǎn)寫。表示發(fā)送者以及發(fā)送完數(shù)據(jù),通常用在發(fā)送者通知對(duì)端,本端即將關(guān)閉。我們把含有FIN標(biāo)識(shí)的報(bào)文稱為結(jié)束報(bào)文段
注意:他們中的多個(gè)可同時(shí)被置為1。
窗口大小(window)[16bit]
指的是接收窗口,窗口的大小,表示源方法最多能接受的字節(jié)數(shù)。
校驗(yàn)和[16bit]
校驗(yàn)和覆蓋了整個(gè)的TCP報(bào)文段:TCP首部和TCP數(shù)據(jù)。這是一個(gè)強(qiáng)制性的字段,一定是由發(fā)端計(jì)算和存儲(chǔ),并由收端進(jìn)行驗(yàn)證。
緊急指針[16bit]
只有當(dāng)URG標(biāo)志置為1時(shí)緊急指針才有效。緊急指針是一個(gè)正的偏移量,和序號(hào)字段中的值相加表示緊急數(shù)據(jù)最后一個(gè)字節(jié)的序號(hào)。TCP的緊急方式是發(fā)送端向另一端發(fā)送緊急數(shù)據(jù)的一種方式。
TCP選項(xiàng)
長(zhǎng)度不定,但長(zhǎng)度必須是32bits的整數(shù)倍。TCP頭部的最后一個(gè)選項(xiàng)字段(options)是可變長(zhǎng)的可選信息。這部分最多包含40字節(jié),因?yàn)門CP頭部最長(zhǎng)是60字節(jié)(其中還包含前面討論的20字節(jié)的固定部分)。典型的TCP選項(xiàng)頭部結(jié)構(gòu)如圖所示。
選項(xiàng)的第一個(gè)字段kind說(shuō)明選項(xiàng)的類型,有的TCP選項(xiàng)沒有后面兩個(gè)字段,僅包含1字節(jié)的kind字段。
第二個(gè)字段length(如果有的話)指定該選項(xiàng)的總長(zhǎng)度,該長(zhǎng)度包括kind字段和length字段占據(jù)的2字節(jié)。
第三個(gè)字段info(如果有的話)是選項(xiàng)的具體信息。
常見的TCP選項(xiàng)有7種,如圖所示
1、kind=0,選項(xiàng)表結(jié)束(EOP)選項(xiàng)
一個(gè)報(bào)文段僅用一次。放在末尾用于填充,用途是說(shuō)明:首部已經(jīng)沒有更多的消息,應(yīng)用數(shù)據(jù)在下一個(gè)32位字開始處。
2、kind=1,空操作(NOP)選項(xiàng)
沒有特殊含義,一般用于將TCP選項(xiàng)的總長(zhǎng)度填充為4字節(jié)的整數(shù)倍。
3、kind=2,最大報(bào)文段長(zhǎng)度(MSS)選項(xiàng)
TCP連接初始化時(shí),通信雙方使用該選項(xiàng)來(lái)協(xié)商最大報(bào)文段長(zhǎng)度。TCP模塊通常將MSS設(shè)置為(MTU-40)字節(jié)(減掉的這40字節(jié)包括20字節(jié)的TCP頭部和20字節(jié)的IP頭部)。這樣攜帶TCP報(bào)文段的IP數(shù)據(jù)報(bào)的長(zhǎng)度就不會(huì)超過(guò)MTU(假設(shè)TCP頭部和IP頭部都不包含選項(xiàng)字段,并且這也是一般情況),從而避免本機(jī)發(fā)生IP分片。對(duì)以太網(wǎng)而言,MSS值是1460(1500-40)字節(jié)。
4、kind=3,窗口擴(kuò)大因子選項(xiàng)
TCP連接初始化時(shí),通信雙方使用該選項(xiàng)來(lái)協(xié)商接收窗口的擴(kuò)大因子。在TCP的頭部中,接收窗口大小是用16位表示的,故最大為65535字節(jié),但實(shí)際上TCP模塊允許的接收窗口大小遠(yuǎn)不止這個(gè)數(shù)(為了提高TCP通信的吞吐量)。窗口擴(kuò)大因子解決了這個(gè)問(wèn)題。
假設(shè)TCP頭部中的接收通告窗口大小是N,窗口擴(kuò)大因子(移位數(shù))是M,那么TCP報(bào)文段的實(shí)際接收通告窗口大小是N*(2^M),或者說(shuō)N左移M位。注意,M的取值范圍是0~14。我們可以通過(guò)修改/proc/sys/net/ipv4/tcp_window_scaling內(nèi)核變量來(lái)啟用或關(guān)閉窗口擴(kuò)大因子選項(xiàng)。
和MSS選項(xiàng)一樣,窗口擴(kuò)大因子選項(xiàng)只能出現(xiàn)在同步報(bào)文段中,否則將被忽略。但同步報(bào)文段本身不執(zhí)行窗口擴(kuò)大操作,即同步報(bào)文段頭部的接收窗口大小就是該TCP報(bào)文段的實(shí)際接收窗口大小。當(dāng)連接建立好之后,每個(gè)數(shù)據(jù)傳輸方向的窗口擴(kuò)大因子就固定不變了。
5、kind=4,選擇性確認(rèn)(SelectiveAcknowledgment,SACK)選項(xiàng)
TCP通信時(shí),如果某個(gè)TCP報(bào)文段丟失,則TCP會(huì)重傳最后被確認(rèn)的TCP報(bào)文段后續(xù)的所有報(bào)文段,這樣原先已經(jīng)正確傳輸?shù)腡CP報(bào)文段也可能重復(fù)發(fā)送,從而降低了TCP性能。SACK技術(shù)正是為改善這種情況而產(chǎn)生的,它使TCP只重新發(fā)送丟失的TCP報(bào)文段,而不用發(fā)送所有未被確認(rèn)的TCP報(bào)文段。選擇性確認(rèn)選項(xiàng)用在連接初始化時(shí),表示是否支持SACK技術(shù)。我們可以通過(guò)修改/proc/sys/net/ipv4/tcp_sack 內(nèi)核變量來(lái)啟用或關(guān)閉選擇性確認(rèn)選項(xiàng)。
6、kind=5,SACK實(shí)際工作的選項(xiàng)
該選項(xiàng)的參數(shù)告訴發(fā)送方本端已經(jīng)收到并緩存的不連續(xù)的數(shù)據(jù)塊,從而讓發(fā)送端可以據(jù)此檢查并重發(fā)丟失的數(shù)據(jù)塊。每個(gè)塊邊沿(edgeofblock)參數(shù)包含一個(gè)4字節(jié)的序號(hào)。其中塊左邊沿表示不連續(xù)塊的第一個(gè)數(shù)據(jù)的序號(hào),而塊右邊沿則表示不連續(xù)塊的最后一個(gè)數(shù)據(jù)的序號(hào)的下一個(gè)序號(hào)。這樣一對(duì)參數(shù)(塊左邊沿和塊右邊沿)之間的數(shù)據(jù)是沒有收到的。因?yàn)橐粋€(gè)塊信息占用8字節(jié),所以TCP頭部選項(xiàng)中實(shí)際上最多可以包含4個(gè)這樣的不連續(xù)數(shù)據(jù)塊(考慮選項(xiàng)類型和長(zhǎng)度占用的2字節(jié))。
7、kind=8,時(shí)間戳選項(xiàng)。
該選項(xiàng)提供了較為準(zhǔn)確的計(jì)算通信雙方之間的回路時(shí)間(RoundTrip Time,RTT)的方法,從而為TCP流量控制提供重要信息。我們可以通過(guò)修改/proc/sys/net/ipv4/tcp_timestamps內(nèi)核變量來(lái)啟用或關(guān)閉時(shí)間戳選項(xiàng)。
以SYN的TCP選項(xiàng)的MSS為例的wireshark分析,其他的大家可以自行分析。
整個(gè)TCP協(xié)議頭部的wireshark解析。
03 TCP數(shù)據(jù)包的編號(hào)(SEQ)
一個(gè)包1400字節(jié),那么一次性發(fā)送大量數(shù)據(jù),就必須分成多個(gè)包。比如,一個(gè)10MB 的文件,需要發(fā)送7100多個(gè)包。
發(fā)送的時(shí)候,TCP協(xié)議為每個(gè)包編號(hào)(sequencenumber,簡(jiǎn)稱SEQ),以便接收的一方按照順序還原。萬(wàn)一發(fā)生丟包,也可以知道丟失的是哪一個(gè)包。
第一個(gè)包的編號(hào)是一個(gè)隨機(jī)數(shù)。為了便于理解,這里就把它稱為1號(hào)包。假定這個(gè)包的負(fù)載長(zhǎng)度是100字節(jié),那么可以推算出下一個(gè)包的編號(hào)應(yīng)該是101。這就是說(shuō),每個(gè)數(shù)據(jù)包都可以得到兩個(gè)編號(hào):自身的編號(hào),以及下一個(gè)包的編號(hào)。接收方由此知道,應(yīng)該按照什么順序?qū)⑺鼈冞€原成原始文件。
這里的編號(hào)就是TCP頭中的確認(rèn)號(hào)。wireshark顯示的Seq和Ack是wireshark重新編號(hào)的。
數(shù)據(jù)包1:發(fā)送序號(hào):532420307(1),確認(rèn)序號(hào):2978637660(1)。數(shù)據(jù)包長(zhǎng)6
數(shù)據(jù)包2:發(fā)送序號(hào):2978637660(1),確認(rèn)序號(hào):532420313(7)。
備注:括號(hào)里是wireshark的編號(hào)。
可以發(fā)現(xiàn):
數(shù)據(jù)包2的發(fā)送序號(hào)是數(shù)據(jù)包1的確認(rèn)序號(hào)。
數(shù)據(jù)包2的確認(rèn)序號(hào)是數(shù)據(jù)包1的發(fā)送序號(hào)+6,也就是加上數(shù)據(jù)包長(zhǎng)。
符合上面的文字描述。
04 三次握手建立連接
三次握手建立連接過(guò)程:
a.請(qǐng)求端(通常稱為客戶)發(fā)送一個(gè)SYN段指明客戶打算連接的服務(wù)器的端口,以及初始序號(hào)(ISN,在這個(gè)例子中為1415531521)。這個(gè)SYN段為報(bào)文段1。
b.服務(wù)器發(fā)回包含服務(wù)器的初始序號(hào)的SYN報(bào)文段(報(bào)文段2)作為應(yīng)答。同時(shí),將確認(rèn)序號(hào)設(shè)置為客戶的ISN加1以對(duì)客戶的SYN報(bào)文段進(jìn)行確認(rèn)。一個(gè)SYN將占用一個(gè)序號(hào)。
c.客戶必須將確認(rèn)序號(hào)設(shè)置為服務(wù)器的ISN加1以對(duì)服務(wù)器的SYN報(bào)文段進(jìn)行確認(rèn)(報(bào)文段3)。
這三個(gè)報(bào)文段完成連接的建立。這個(gè)過(guò)程也稱為三次握手(three-wayhandshake)。
用wirshark抓包如下:
可以看到三次握手確定了雙方間包的序號(hào)、最大接受數(shù)據(jù)的大小(window)以及MSS(MaximumSegment Size)。
MSS = MTU - IP頭-TCP頭,MTU表示最大傳輸單元,我們?cè)贗P頭分析的時(shí)候會(huì)講到,它一般為1500個(gè)字節(jié)。IP頭和TCP頭部帶可選選項(xiàng)的時(shí)候都是20個(gè)字節(jié)。這樣的話MSS=1500- 20 -20 = 1460。
MSS限制了TCP包攜帶數(shù)據(jù)的大小,它的意思就是當(dāng)應(yīng)用層向傳輸層提交數(shù)據(jù)通過(guò)TCP協(xié)議進(jìn)行傳輸時(shí),如果應(yīng)用層的數(shù)據(jù)大于MSS就必須分段,分成多個(gè)段,逐個(gè)的發(fā)過(guò)去。這部分內(nèi)容是不是IP分片,不要和IP分片混淆了,IP分片是IP協(xié)議層的數(shù)據(jù)報(bào)分片,這是TCP的分片,IP協(xié)議分片詳細(xì)請(qǐng)看《IP協(xié)議詳解》。
我們wireshar抓包顯示MSS都是1460,這樣顯示不出來(lái)握手的協(xié)商機(jī)制。假設(shè)客戶端的MSS是4312,服務(wù)器的MSS是1460,那么握手過(guò)程中的協(xié)商可以下圖形象表示。
其中,第1 次和第2 次握手包的TCP 首部包含MSS 選項(xiàng),互相通知對(duì)方網(wǎng)絡(luò)接口能夠適應(yīng)的MSS 的大小,然后雙方會(huì)使用較小的MSS 值進(jìn)行傳輸。
前面講解TCP頭中flg中就有SYN標(biāo)志,在wireshark抓包中也有顯示。
讀到這里,好像一切順理成章,決定既然互聯(lián)網(wǎng)“先驅(qū)”定義了三次握手建立,那么就是三次握手建立連接。可有些人會(huì)有疑問(wèn),為什么兩次握手不能。
比如A給B東西,
A說(shuō):我要和你建立,你準(zhǔn)備好了嗎?
B說(shuō):好的,我準(zhǔn)備好了。
A直接把東西給B。
這樣的邏輯在生活中好像一點(diǎn)毛病也沒有,但其實(shí)這樣是不行,3次握手完成兩個(gè)重要的功能,既要雙方做好發(fā)送數(shù)據(jù)的準(zhǔn)備工作(雙方都知道彼此已準(zhǔn)備好),也要允許雙方就初始序列號(hào)進(jìn)行協(xié)商,這個(gè)序列號(hào)在握手過(guò)程中被發(fā)送和確認(rèn)。
現(xiàn)在把三次握手改成僅需要兩次握手,死鎖是可能發(fā)生的。其實(shí)上面有個(gè)“坑”,那就是一開始我們限制了A給B東西,但實(shí)際的TCP通信中,連接建立了,可以客戶端主動(dòng)和服務(wù)器通信,也可以服務(wù)器主動(dòng)和客戶端通信,如果兩次握手,B收到A的握手申請(qǐng),發(fā)送好的,我準(zhǔn)備好了。這時(shí)候B在想,A如果收不到怎么辦,A到底有沒有收到啊,我(B)能不能向A發(fā)數(shù)據(jù)???
所以需要三次握手。
A說(shuō):我和你建立,你準(zhǔn)備好了嗎?
B說(shuō):好的,我準(zhǔn)備好了。
A說(shuō):我知道你準(zhǔn)備好了(我也準(zhǔn)備好了)。
開始愉快的相互傳輸數(shù)據(jù)。
05 四次揮手?jǐn)嚅_連接
四次揮手?jǐn)嚅_連接過(guò)程:
a.現(xiàn)在的網(wǎng)絡(luò)通信都是基于socket實(shí)現(xiàn)的,當(dāng)客戶端將自己的socket進(jìn)行關(guān)閉時(shí),內(nèi)核協(xié)議棧會(huì)向服務(wù)器自動(dòng)發(fā)送一個(gè)FIN置位的包,請(qǐng)求斷開連接。我們稱首先發(fā)起斷開請(qǐng)求的一方稱為主動(dòng)斷開方。
b.服務(wù)器端收到請(qǐng)客端的FIN斷開請(qǐng)求后,內(nèi)核協(xié)議棧會(huì)立即發(fā)送一個(gè)ACK包作為應(yīng)答,表示已經(jīng)收到客戶端的請(qǐng)求。
c.服務(wù)器運(yùn)行一段時(shí)間后,關(guān)閉了自己的socket。這個(gè)時(shí)候內(nèi)核協(xié)議棧會(huì)向客戶端發(fā)送一個(gè)FIN置位的包,請(qǐng)求斷開連接。
d.客戶端收到服務(wù)端發(fā)來(lái)的FIN斷開請(qǐng)求后,會(huì)發(fā)送一個(gè)ACK做出應(yīng)答,表示已經(jīng)收到服務(wù)端的請(qǐng)求。
用wirshar抓包分析如下:
前面講解TCP頭中flg中就有FIN標(biāo)志,在wireshark抓包中也有顯示。
下圖類比四次揮手過(guò)程:
這里有個(gè)問(wèn)題,如果有同學(xué)自己wireshark抓包分析的話(我提供的wireshark文件第一次通信也是這種情況),會(huì)發(fā)現(xiàn)下面情況:
怎么只有3次揮手,應(yīng)用程序出問(wèn)題了?wirshark自行”合并“了?為什么別人抓包就有四次揮手?jǐn)嚅_?
這跟Wireshark沒有關(guān)系,跟實(shí)現(xiàn)有關(guān)。四次揮手,都知道是客戶端和服務(wù)器之間交互的四個(gè)報(bào)文,F(xiàn)IN、ACK、FIN、ACK。但抓包來(lái)看,卻不是每次如教科書說(shuō)的那樣。首先要搞明白這個(gè)FIN報(bào)文的真正用途,F(xiàn)IN報(bào)文用在本端沒有數(shù)據(jù)發(fā)送給對(duì)方時(shí),關(guān)閉從本端到對(duì)端的連接。但是并不影響從對(duì)方到本端的連接,也就是說(shuō)本端仍然可以接收對(duì)方的數(shù)據(jù)。即發(fā)送通道關(guān)閉,接收通道正常。如果對(duì)方收到本端FIN報(bào)文時(shí),對(duì)方的接收通道就會(huì)關(guān)閉。此時(shí),如果對(duì)方也沒有數(shù)據(jù)發(fā)給本端,那么對(duì)方也會(huì)發(fā)送FIN給本端,用于關(guān)閉從對(duì)方到本端的連接,這時(shí)候就可能出現(xiàn)ACK和FIN合在一起的情況。當(dāng)然,如果對(duì)方仍然有數(shù)據(jù)發(fā)送,那么就等數(shù)據(jù)發(fā)完,再發(fā)FIN來(lái)關(guān)閉連接,這時(shí)候就是四次揮手了。因此,四次揮手變成三次,跟wireshark沒關(guān)系,跟數(shù)據(jù)的收發(fā)雙方才有關(guān)系,從這也能看出tcp是雙工通信了。現(xiàn)在的很多的實(shí)現(xiàn)都是合并在一起,三個(gè)過(guò)程,主要是為了效率和安全。
TCP 連接必須經(jīng)過(guò)時(shí)間2MSL 后才真正釋放掉(2MSL的時(shí)間的用意---為了保證A 發(fā)送的最后一個(gè)ACK 報(bào)文段能夠到達(dá)B.防止“已失效的連接請(qǐng)求報(bào)文段”出現(xiàn)在本連接中.A在發(fā)送完最后一個(gè)ACK 報(bào)文段后,再經(jīng)過(guò)時(shí)間2MSL,就可以使本連接持續(xù)的時(shí)間內(nèi)所產(chǎn)生的所有報(bào)文段,都從網(wǎng)絡(luò)中消失.這樣就可以使下一個(gè)新的連接中不會(huì)出現(xiàn)這種舊的連接請(qǐng)求報(bào)文段)。
06 TCP可靠性的保證 TCP采用一種名為“帶重傳功能的肯定確認(rèn)(positiveacknowledge withretransmission)”的技術(shù)作為提供可靠數(shù)據(jù)傳輸服務(wù)的基礎(chǔ)。這項(xiàng)技術(shù)要求接收方收到數(shù)據(jù)之后向源站回送確認(rèn)信息ACK。發(fā)送方對(duì)發(fā)出的每個(gè)分組都保存一份記錄,在發(fā)送下一個(gè)分組之前等待確認(rèn)信息。發(fā)送方還在送出分組的同時(shí)啟動(dòng)一個(gè)定時(shí)器,并在定時(shí)器的定時(shí)期滿而確認(rèn)信息還沒有到達(dá)的情況下,重發(fā)剛才發(fā)出的分組。
下圖a表示帶重傳功能的肯定確認(rèn)協(xié)議傳輸數(shù)據(jù)的情況,下圖a表示分組丟失引起超時(shí)和重傳。為了避免由于網(wǎng)絡(luò)延遲引起遲到的確認(rèn)和重復(fù)的確認(rèn),協(xié)議規(guī)定在確認(rèn)信息中稍帶一個(gè)分組的序號(hào),使接收方能正確將分組與確認(rèn)關(guān)聯(lián)起來(lái)。
下圖a可以看出,雖然網(wǎng)絡(luò)具有同時(shí)進(jìn)行雙向通信的能力,但由于在接到前一個(gè)分組的確認(rèn)信息之前必須推遲下一個(gè)分組的發(fā)送,簡(jiǎn)單的肯定確認(rèn)協(xié)議浪費(fèi)了大量寶貴的網(wǎng)絡(luò)帶寬。為此,TCP使用滑動(dòng)窗口的機(jī)制來(lái)提高網(wǎng)絡(luò)吞吐量,同時(shí)解決端到端的流量控制。
07 滑動(dòng)窗口技術(shù)
TCP的滑動(dòng)窗口主要有兩個(gè)作用,一是提供TCP的可靠性,二是提供TCP的流控特性。同時(shí)滑動(dòng)窗口機(jī)制還體現(xiàn)了TCP面向字節(jié)流的設(shè)計(jì)思路。
TCP的Window是一個(gè)16bit位字段,它代表的是窗口的字節(jié)容量,也就是TCP的標(biāo)準(zhǔn)窗口最大為2^16-1=65535個(gè)字節(jié)。另外在TCP的選項(xiàng)字段中還包含了一個(gè)TCP窗口擴(kuò)大因子,option-kind為3,詳細(xì)請(qǐng)看上文。
滑動(dòng)窗口技術(shù)是簡(jiǎn)單的帶重傳的肯定確認(rèn)機(jī)制的一個(gè)更復(fù)雜的變形,它允許發(fā)送方在等待一個(gè)確認(rèn)信息之前可以發(fā)送多個(gè)分組。
所以,TCP的滑動(dòng)窗口的可靠性也是建立在“確認(rèn)重傳”基礎(chǔ)上的。
TCP 滑動(dòng)窗口分為:發(fā)送窗口和接收窗口。
發(fā)送方的發(fā)送緩存內(nèi)的數(shù)據(jù)都可以被分為4類:
已發(fā)送,已收到ACK
已發(fā)送,未收到ACK
未發(fā)送,但允許發(fā)送
未發(fā)送,但不允許發(fā)送
其中類型2和3都屬于發(fā)送窗口。
接收方的緩存數(shù)據(jù)分為3類:
已接收
未接收但準(zhǔn)備接收
未接收而且不準(zhǔn)備接收
如下圖所示,發(fā)送方要發(fā)送一個(gè)分組序列,滑動(dòng)窗口協(xié)議在分組序列中放置一個(gè)固定長(zhǎng)度的窗口,然后將窗口內(nèi)的所有分組都發(fā)送出去;當(dāng)發(fā)送方收到對(duì)窗口內(nèi)第一個(gè)分組的確認(rèn)信息時(shí),它可以向后滑動(dòng)并發(fā)送下一個(gè)分組;隨著確認(rèn)的不斷到達(dá),窗口也在不斷的向后滑動(dòng)。
上面的解釋,對(duì)于不熟悉滑動(dòng)窗口的同學(xué),可能看不太明白。下面將詳細(xì)講述一下。
上面講解三次握手建立連接時(shí)說(shuō)到,握手過(guò)程中商議了MSS,也就是每一包的數(shù)據(jù)長(zhǎng)度。抓包中也顯示的確是1460字節(jié)傳輸?shù)摹?/p>
但是1460字節(jié)不是整數(shù),不方便我們快速計(jì)算,下面講解將MSS假設(shè)為1000,這樣方面快速理解。
在進(jìn)行數(shù)據(jù)傳輸時(shí),如果傳輸?shù)臄?shù)據(jù)比較大(大于1000),就需要拆分為多個(gè)數(shù)據(jù)包進(jìn)行發(fā)送。TCP協(xié)議需要對(duì)數(shù)據(jù)進(jìn)行確認(rèn)后,才可以發(fā)送下一個(gè)數(shù)據(jù)包,
從上圖中可以看到,發(fā)送端每發(fā)送一個(gè)數(shù)據(jù)包,都需要得到接收端的確認(rèn)應(yīng)答以后,才可以發(fā)送下一個(gè)數(shù)據(jù)包。這樣一來(lái),就會(huì)在等待確認(rèn)應(yīng)答包環(huán)節(jié)浪費(fèi)時(shí)間。為了避免這種情況,TCP引入了窗口概念。窗口大小指的是不需要等待確認(rèn)應(yīng)答包而可以繼續(xù)發(fā)送數(shù)據(jù)包的最大值。
例如,窗口大小為3,數(shù)據(jù)包的傳輸如圖所示。
從上圖中可以看到,發(fā)送端發(fā)送第一個(gè)數(shù)據(jù)包(1-1000),沒有等待對(duì)應(yīng)的確認(rèn)應(yīng)答包,就繼續(xù)發(fā)送第二個(gè)數(shù)據(jù)包(1001-2000)和第三個(gè)包(2001-3000)。當(dāng)收到第3個(gè)數(shù)據(jù)包的確認(rèn)應(yīng)答包時(shí),會(huì)連續(xù)發(fā)送3個(gè)數(shù)據(jù)包(3001-4000,4001-5000,5001-6000)。當(dāng)收到第6個(gè)數(shù)據(jù)包的確認(rèn)應(yīng)答包時(shí),又會(huì)發(fā)送3個(gè)數(shù)據(jù)包(6001-7000,7001-8000,8001-9000)。
以這種方式發(fā)送,就可以省去多個(gè)數(shù)據(jù)包(第1、2、4、5、7、8個(gè))的確認(rèn)應(yīng)答包時(shí)間,從而避免了網(wǎng)絡(luò)的吞吐量的降低。
這樣就引出了窗口的概念,窗口大小指的是可以發(fā)送數(shù)據(jù)包的最大數(shù)量。建議讀到這里,剛才對(duì)窗口不太理解的同學(xué),向上翻翻,再理解一下滑動(dòng)窗口的圖示。
那么,此時(shí)窗口就通過(guò)滑動(dòng)的方式,向后移動(dòng),確保下一次發(fā)送仍然可以發(fā)送窗口大小的數(shù)據(jù)包。這樣的發(fā)送方式被稱為滑動(dòng)窗口機(jī)制。設(shè)置窗口大小為3,滑動(dòng)窗口機(jī)制原理如圖所示。
上圖中,每1000 個(gè)字節(jié)表示一個(gè)數(shù)據(jù)包。發(fā)送端同時(shí)發(fā)送了3個(gè)數(shù)據(jù)包(2001-5000),接收端響應(yīng)的確認(rèn)應(yīng)答包為“下一個(gè)發(fā)送4001”,表示接收端成功響應(yīng)了前兩個(gè)數(shù)據(jù)包,沒有響應(yīng)最后一個(gè)數(shù)據(jù)包。此時(shí),最后一個(gè)數(shù)據(jù)包要保留在窗口中。
由于窗口大小為3,發(fā)送端除了最后一個(gè)包以外,還可以繼續(xù)發(fā)送下兩個(gè)數(shù)據(jù)包(5001-6000和6001-7000)。窗口滑動(dòng)到7001 處。
08 窗口滑動(dòng)的數(shù)據(jù)重發(fā)
在進(jìn)行數(shù)據(jù)包傳輸時(shí),難免會(huì)出現(xiàn)數(shù)據(jù)丟失情況。這種情況一般分為兩種。
第一種,如果未使用滑動(dòng)窗口機(jī)制,發(fā)送的數(shù)據(jù)包沒有收到確認(rèn)應(yīng)答包,那么數(shù)據(jù)都會(huì)被重發(fā);如果使用了滑動(dòng)窗口機(jī)制,即使確認(rèn)應(yīng)答包丟失,也不會(huì)導(dǎo)致數(shù)據(jù)包重發(fā)。
第二種,發(fā)送的數(shù)據(jù)包丟失,將導(dǎo)致數(shù)據(jù)包重發(fā)。
下面詳細(xì)介紹使用滑動(dòng)窗口機(jī)制的兩種情況。
確認(rèn)應(yīng)答包丟失
這種情況指的是前面發(fā)送的數(shù)據(jù)包沒有收到對(duì)應(yīng)的確認(rèn)應(yīng)答。當(dāng)收到后面數(shù)據(jù)包的確認(rèn)應(yīng)答包,表示前面的數(shù)據(jù)包已經(jīng)成功被接收端接收了,發(fā)送端不需要重新發(fā)送前面的數(shù)據(jù)包了。如圖所示。
下面分為5 部分對(duì)上圖進(jìn)行講解。
1) 發(fā)送端第1 次發(fā)送數(shù)據(jù)包:這里設(shè)置的窗口大小為3,可以最大發(fā)送3 個(gè)數(shù)據(jù)包。發(fā)送端同時(shí)發(fā)送3 個(gè)數(shù)據(jù)包1-1000、1001-2000和2001-3000。
2) 接收端返回確認(rèn)應(yīng)答包:接收端接收到這些數(shù)據(jù),并給出確認(rèn)應(yīng)答包。數(shù)據(jù)包1-1000 和數(shù)據(jù)包2001-3000 的確認(rèn)應(yīng)答包沒有丟失,但是數(shù)據(jù)包1001-2000 的確認(rèn)應(yīng)答包丟失了。
3) 發(fā)送端第2 次發(fā)送數(shù)據(jù)包:發(fā)送端收到接收端發(fā)來(lái)的確認(rèn)應(yīng)答包,雖然沒有收到數(shù)據(jù)包1001-2000 的確認(rèn)應(yīng)答包,但是收到了數(shù)據(jù)包2001-3000 的確認(rèn)應(yīng)答包。判斷第一次發(fā)送的3 個(gè)數(shù)據(jù)包都成功到達(dá)了接收端。再次發(fā)送3 個(gè)數(shù)據(jù)包3001-4000、4001-5000和5001-6000。
4) 接收端返回確認(rèn)應(yīng)答包:接收端接收到這些數(shù)據(jù),并給出確認(rèn)應(yīng)答包。數(shù)據(jù)包3001-4000 和數(shù)據(jù)包4001-5000 的確認(rèn)應(yīng)答包丟失了,但是數(shù)據(jù)包5001-6000 沒有丟失。
5) 發(fā)送端第3 次發(fā)送數(shù)據(jù)包:發(fā)送端收到接收端發(fā)來(lái)的確認(rèn)應(yīng)答包,查看到數(shù)據(jù)包5001-6000 收到了確認(rèn)應(yīng)答包。判斷第2 次發(fā)送的3 個(gè)數(shù)據(jù)包都成功到達(dá)了接收端。再次發(fā)送3 個(gè)數(shù)據(jù)包6001-7000、7001-8000和8001-9000。
發(fā)送數(shù)據(jù)包丟失
這種情況指的是發(fā)送端發(fā)送的部分?jǐn)?shù)據(jù)包沒有達(dá)到接收端。那么,如果在接收端收到的數(shù)據(jù)包,不是本應(yīng)該要接收的數(shù)據(jù)包,那么就會(huì)給發(fā)送端返回消息,告訴發(fā)送端自己應(yīng)該接收的數(shù)據(jù)包。
如果發(fā)送端連續(xù)收到3 次這樣的數(shù)據(jù)包,就認(rèn)為該數(shù)據(jù)包成功發(fā)送到接收端,這時(shí)就開始重發(fā)該數(shù)據(jù)包。如圖所示。
下面分為7 部分對(duì)上圖進(jìn)行講解。
1) 發(fā)送端發(fā)送數(shù)據(jù)包:這里窗口大小為4,發(fā)送端發(fā)送4 個(gè)數(shù)據(jù)包,分別為1-1000、1001-2000、2001-3000和3001-4000。
2) 接收端返回確認(rèn)應(yīng)答包:接收端接收到這些數(shù)據(jù),并給出確認(rèn)應(yīng)答包。接收端收到了數(shù)據(jù)包1-1000,返回了確認(rèn)應(yīng)答包;收到了數(shù)據(jù)包1001-2000,返回了確認(rèn)應(yīng)答包;但是數(shù)據(jù)包2001-3000,在發(fā)送過(guò)程中丟失了,沒有成功到達(dá)接收端。數(shù)據(jù)包3001-4000 沒有丟失,成功到達(dá)了接收端,但是該數(shù)據(jù)包不是接收端應(yīng)該接收的數(shù)據(jù)包,數(shù)據(jù)包2001-3000 才是真正應(yīng)該接收的數(shù)據(jù)包。因此收到數(shù)據(jù)包3001-4000 以后,接收端第一次返回下一個(gè)應(yīng)該發(fā)送2001 的數(shù)據(jù)包的確認(rèn)應(yīng)答包。
3)發(fā)送端發(fā)送數(shù)據(jù)包:發(fā)送端仍然繼續(xù)向接收端發(fā)送4 個(gè)數(shù)據(jù)包,分別為4001-5000、5001-6000、6001-7000和7001-8000。
4) 接收端返回確認(rèn)應(yīng)答包:接收端接收到這些數(shù)據(jù),并給出確認(rèn)應(yīng)答包。當(dāng)接收端收到數(shù)據(jù)包4001-5000 時(shí),發(fā)現(xiàn)不是自己應(yīng)該接收的數(shù)據(jù)包2001-3000,第二次返回下一個(gè)應(yīng)該發(fā)送2001 的數(shù)據(jù)包的確認(rèn)應(yīng)答包。當(dāng)接收端收到數(shù)據(jù)包5001-6000 時(shí),仍然發(fā)現(xiàn)不是自己應(yīng)該接收的數(shù)據(jù)包2001-3000,第三次返回下一個(gè)應(yīng)該發(fā)送2001 的數(shù)據(jù)包的確認(rèn)應(yīng)答包。以此類推直到接收完所有數(shù)據(jù)包,接收端都返回下一個(gè)應(yīng)該發(fā)送2001 的數(shù)據(jù)包的確認(rèn)應(yīng)答包。
5)發(fā)送端重發(fā)數(shù)據(jù)包:發(fā)送端連續(xù)3 次收到接收端發(fā)來(lái)的下一個(gè)應(yīng)該發(fā)送2001 的數(shù)據(jù)包的確認(rèn)應(yīng)答包,認(rèn)為數(shù)據(jù)包2001-3000 丟失了,就進(jìn)行重發(fā)該數(shù)據(jù)包。
6)接收端收到重發(fā)數(shù)據(jù)包:接收端收到重發(fā)數(shù)據(jù)包以后,查看這次是自己應(yīng)該接收的數(shù)據(jù)包2001-3000,并返回確認(rèn)應(yīng)答包,告訴發(fā)送端,下一個(gè)該接收8001 的數(shù)據(jù)包了。
7)發(fā)送端發(fā)送數(shù)據(jù)包:發(fā)送端收到確認(rèn)應(yīng)答包后,繼續(xù)發(fā)送窗口大小為4 的數(shù)據(jù)包,分別為8001-9000、9001-10000、10001-11000和11001-12000。 09 TCP流控制 在使用滑動(dòng)窗口機(jī)制進(jìn)行數(shù)據(jù)傳輸時(shí),發(fā)送方根據(jù)實(shí)際情況發(fā)送數(shù)據(jù)包,接收端接收數(shù)據(jù)包。但是,接收端處理數(shù)據(jù)包的能力是不同的。
1)如果窗口過(guò)小,發(fā)送端發(fā)送少量的數(shù)據(jù)包,接收端很快就處理了,并且還能處理更多的數(shù)據(jù)包。這樣,當(dāng)傳輸比較大的數(shù)據(jù)時(shí)需要不停地等待發(fā)送方,造成很大的延遲。
2)如果窗口過(guò)大,發(fā)送端發(fā)送大量的數(shù)據(jù)包,而接收端處理不了這么多的數(shù)據(jù)包,這樣,就會(huì)堵塞鏈路。如果丟棄這些本應(yīng)該接收的數(shù)據(jù)包,又會(huì)觸發(fā)重發(fā)機(jī)制。
3) 為了避免這種現(xiàn)象的發(fā)生,TCP提供了流控制。所謂的流控制就是使用不同的窗口大小發(fā)送數(shù)據(jù)包。發(fā)送端第一次以窗口大小(該窗口大小是根據(jù)鏈路帶寬的大小來(lái)決定的)發(fā)送數(shù)據(jù)包,接收端接收這些數(shù)據(jù)包,并返回確認(rèn)應(yīng)答包,告訴發(fā)送端自己下次希望收到的數(shù)據(jù)包是多少(新的窗口大小),發(fā)送端收到確認(rèn)應(yīng)答包以后,將以該窗口大小進(jìn)行發(fā)送數(shù)據(jù)包。
TCP 流控制過(guò)程如圖所示。
為了方便講解,將上圖以發(fā)送端發(fā)送數(shù)據(jù)包進(jìn)行分隔,將其分為3 部分進(jìn)行講解。
第一部分
發(fā)送端根據(jù)當(dāng)前鏈路帶寬大小決定發(fā)送數(shù)據(jù)包的窗口大小。這里,窗口大小為3,表示可以發(fā)送3 個(gè)數(shù)據(jù)包。因此發(fā)送端發(fā)送了3 個(gè)數(shù)據(jù)包,分別為1-1000、1001-2000和2001-3000。
接收端接收這些數(shù)據(jù)包,但是只能處理2 個(gè)數(shù)據(jù)包,第3 個(gè)數(shù)據(jù)包2001-3000 沒有被處理。因此返回確認(rèn)應(yīng)答包,設(shè)置窗口大小為2,告訴發(fā)送端自己現(xiàn)在只能處理2 個(gè)數(shù)據(jù)包,下一次請(qǐng)發(fā)送2 個(gè)數(shù)據(jù)包。
第二部分
發(fā)送端接收到確認(rèn)應(yīng)答包,查看到接收端返回窗口大小為2,知道接收端只處理了2 個(gè)數(shù)據(jù)包。發(fā)過(guò)去的第3 個(gè)數(shù)據(jù)包2001-3000 沒有被處理。這說(shuō)明此時(shí)接收端只能處理2 個(gè)數(shù)據(jù)包,第3 個(gè)數(shù)據(jù)包還需要重新發(fā)送。
因此發(fā)送端發(fā)送2 個(gè)數(shù)據(jù)包2001-3000 和3001-4000。接收端收到這兩個(gè)數(shù)據(jù)包并進(jìn)行了處理。此時(shí),還是只能處理2 個(gè)窗口,繼續(xù)向發(fā)送端發(fā)送確認(rèn)應(yīng)答包,設(shè)置窗口為2,告訴發(fā)送端,下一個(gè)應(yīng)該接收4001 的數(shù)據(jù)包。
第三部分
發(fā)送端接收到確認(rèn)應(yīng)答包,查看到接收端返回窗口大小為2。說(shuō)明接收端接收了上次發(fā)送的2 個(gè)數(shù)據(jù)包。此時(shí)仍然可以處理2 個(gè)數(shù)據(jù)包,繼續(xù)發(fā)送數(shù)據(jù)包4001-5000 和5001-6000。
如果在接收端返回的確認(rèn)應(yīng)答包中,窗口設(shè)置為0,則表示現(xiàn)在不能接收任何數(shù)據(jù)。這時(shí),發(fā)送端將不會(huì)再發(fā)送數(shù)據(jù)包,只有等待接收端發(fā)送窗口更新通知才可以繼續(xù)發(fā)送數(shù)據(jù)包。
如果這個(gè)更新通知在傳輸中丟失了,那么就可能導(dǎo)致無(wú)法繼續(xù)通信。為了避免這樣的情況發(fā)生,發(fā)送端會(huì)時(shí)不時(shí)地發(fā)送窗口探測(cè)包,該包僅有1個(gè)字節(jié),用來(lái)獲取最新的窗口大小的信息。
原理如圖所示。
下面介紹上圖所示的獲取窗口更新數(shù)據(jù)包的原理。
1) 發(fā)送端發(fā)送數(shù)據(jù)。發(fā)送端以窗口大小為2,發(fā)送了2 個(gè)數(shù)據(jù)包,分別為4001-5000 和5001-6000。接收端接收到這些數(shù)據(jù)以后,緩沖區(qū)滿了,無(wú)法再處理數(shù)據(jù),于是向發(fā)送端返回確認(rèn)應(yīng)答包,告訴它下一個(gè)接收6001 的數(shù)據(jù),但是現(xiàn)在處理不了數(shù)據(jù),先暫停發(fā)送數(shù)據(jù),設(shè)置窗口大小為0。
2)發(fā)送端暫停發(fā)送數(shù)據(jù)。發(fā)送端收到確認(rèn)應(yīng)答包,查看到下一次發(fā)送的是6001 的數(shù)據(jù),但窗口大小為0,得知接收端此時(shí)無(wú)法處理數(shù)據(jù)。此時(shí),不進(jìn)行發(fā)送數(shù)據(jù),進(jìn)入等待狀態(tài)。
3)接收端發(fā)送窗口大小更新包。當(dāng)接收端處理完發(fā)送端之前發(fā)來(lái)的數(shù)據(jù)包以后,將會(huì)給發(fā)送端發(fā)送一個(gè)窗口大小更新包,告訴它,此時(shí)可以發(fā)送的數(shù)據(jù)包的數(shù)量。這里設(shè)置窗口大小為3,表示此時(shí)可以處理3 個(gè)數(shù)據(jù)包,但是該數(shù)據(jù)包丟失了,沒有發(fā)送到發(fā)送端。
4)發(fā)送端發(fā)送窗口探測(cè)包。由于窗口大小更新包丟失,發(fā)送端的等待時(shí)間超過(guò)了重發(fā)超時(shí)時(shí)間。此時(shí),發(fā)送端向接收端發(fā)送一個(gè)窗口探測(cè)包,大小為1 字節(jié),這里是6001。
5)接收端再次發(fā)送窗口大小更新包。接收端收到發(fā)送端發(fā)來(lái)的探測(cè)包,再次發(fā)送窗口大小更新包,窗口大小為3。
6)發(fā)送端發(fā)送數(shù)據(jù)。發(fā)送端接收到窗口大小更新包,查看到應(yīng)該發(fā)的是6001 的數(shù)據(jù)包,窗口大小為3,可以發(fā)送3 個(gè)數(shù)據(jù)包。因此發(fā)送了數(shù)據(jù)包,分別為6001-7000、7001-8000和8001-9000。 10 網(wǎng)線“斷”了怎么辦 對(duì)于TCP鏈接來(lái)說(shuō),他們之間一旦建立了連接,那么可以一直沒有消息通訊。TCP連接的雙方都沒有向?qū)Ψ桨l(fā)送數(shù)據(jù),則在兩個(gè)TCP模塊之間不交換任何信息。
只要兩端的主機(jī)沒有被重啟,則連接依然保持建立,不管中間路由器可以崩潰和重啟,還是電話線被掛斷再連通。這意味著我們可以啟動(dòng)一個(gè)客戶與服務(wù)器建立一個(gè)連接,然后離去數(shù)小時(shí)、數(shù)天、數(shù)個(gè)星期或者數(shù)月,而連接依然保持。
這對(duì)于客戶端來(lái)說(shuō),倒還好一點(diǎn),畢竟不會(huì)有那么多的連接被占用,對(duì)于服務(wù)器來(lái)說(shuō),就是一個(gè)很糟糕的事情,這種連接無(wú)疑是一種僵尸連接,平白無(wú)辜的占用著服務(wù)器的資源,一旦這種連接非常多,服務(wù)器往往會(huì)因?yàn)檫B接數(shù)量的限制,導(dǎo)致沒有辦法接入新的客戶端。
這個(gè)時(shí)候,其實(shí)就需要一種定時(shí)探測(cè)對(duì)端連接是否還存活的機(jī)制存在,如此以來(lái)彼此都能知道對(duì)方的狀態(tài),是否還能繼續(xù)使用。
這種機(jī)制,對(duì)于TCP來(lái)說(shuō),就是TCP的保活機(jī)制。TCP還設(shè)有一個(gè)保活計(jì)時(shí)器,服務(wù)器每收到一次客戶端的請(qǐng)求后都會(huì)重新復(fù)位這個(gè)計(jì)時(shí)器,時(shí)間通常是設(shè)置為2小時(shí),若兩小時(shí)還沒有收到客戶端的任何數(shù)據(jù),服務(wù)器就會(huì)發(fā)送一個(gè)探測(cè)報(bào)文段,以后每隔75秒鐘發(fā)送一次,俗稱“心跳”。若一連發(fā)送10個(gè)探測(cè)報(bào)文仍然沒反應(yīng),服務(wù)器就認(rèn)為客戶端出了故障,接著就關(guān)閉連接。
TCP具有保活器,但我建議在應(yīng)用層最好還要設(shè)計(jì)一個(gè)“心跳”用來(lái)維持TCP連接,時(shí)間間隔可自行確定。再插一嘴,具有保活器的TCP就是長(zhǎng)連接。
長(zhǎng)連接:建立一個(gè)連接,多個(gè)請(qǐng)求復(fù)用這個(gè)連接,一直用同一個(gè)鏈接傳輸數(shù)據(jù),最后再關(guān)閉連接。
短連接:建立一個(gè)連接,傳輸一個(gè)請(qǐng)求,發(fā)送完數(shù)據(jù)后就關(guān)閉連接。
TCP具有保活器優(yōu)點(diǎn):
1.在連接兩個(gè)端系統(tǒng)的網(wǎng)絡(luò)出現(xiàn)臨時(shí)故障的時(shí)候,保活選項(xiàng)會(huì)引起一個(gè)實(shí)際上很好的連接終止。例如,如果在一個(gè)中間路由器崩潰并重新啟動(dòng)時(shí)發(fā)送保活探查,那么TCP會(huì)認(rèn)為客戶的主機(jī)已經(jīng)崩潰,而實(shí)際上所發(fā)生的并非如此。
2.保活功能主要是為服務(wù)器應(yīng)用程序提供的。服務(wù)器應(yīng)用程序希望知道客戶主機(jī)是否崩潰,從而可以代表客戶使用資源,及時(shí)回收這些資源。
TCP具有保活器缺點(diǎn):
保活并不是TCP規(guī)范中的一部分。HostRequirements RFC提供了3個(gè)不使用保活定時(shí)器的理由:
1)在出現(xiàn)短暫差錯(cuò)的情況下,這可能會(huì)使一個(gè)非常好的連接釋放掉;
2)它們耗費(fèi)不必要的帶寬;
3)在按分組計(jì)費(fèi)的情況下會(huì)在互聯(lián)網(wǎng)上花掉更多的錢。
原文標(biāo)題:1萬(wàn)字30張圖說(shuō)清TCP協(xié)議
文章出處:【微信公眾號(hào):玩轉(zhuǎn)單片機(jī)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
責(zé)任編輯:haq
-
IP
+關(guān)注
關(guān)注
5文章
1718瀏覽量
149965 -
TCP
+關(guān)注
關(guān)注
8文章
1378瀏覽量
79302
原文標(biāo)題:1萬(wàn)字30張圖說(shuō)清TCP協(xié)議
文章出處:【微信號(hào):mcu168,微信公眾號(hào):硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
TCP協(xié)議的常見應(yīng)用場(chǎng)景
如何優(yōu)化TCP協(xié)議的性能
TCP協(xié)議與UDP協(xié)議的區(qū)別
什么是TCP協(xié)議及其工作原理
ID讀卡器TCP協(xié)議QT小程序開發(fā)
![ID讀卡器<b class='flag-5'>TCP</b><b class='flag-5'>協(xié)議</b>QT小程序開發(fā)](https://file1.elecfans.com/web3/M00/04/5B/wKgZPGdzTm2AN68GAAPBNk4wtZw082.png)
什么是socket編程 socket與tcp/ip協(xié)議的關(guān)系
高防服務(wù)器托管:全方位解析與應(yīng)用
TCP協(xié)議是什么
一文了解TCP/IP協(xié)議
![一文了解<b class='flag-5'>TCP</b>/IP<b class='flag-5'>協(xié)議</b>](https://file1.elecfans.com/web2/M00/01/F4/wKgaomazJM6AUmLUAAAopE8gQog159.png)
華納云:TCP IP協(xié)議的發(fā)展和優(yōu)勢(shì)
TCP IP協(xié)議屬性設(shè)置中的IP配置
紫光展銳與中興通訊簽署全方位5G戰(zhàn)略合作框架協(xié)議
mqtt協(xié)議和tcp協(xié)議區(qū)別
通信必備知識(shí)!TCP與UDP協(xié)議介紹及使用
![通信必備知識(shí)!<b class='flag-5'>TCP</b>與UDP<b class='flag-5'>協(xié)議</b><b class='flag-5'>介紹</b>及使用](https://file.elecfans.com/web2/M00/3E/6A/pYYBAGJhBGGAGyDYAACBPQuBZQI711.png)
評(píng)論