本文將簡(jiǎn)單介紹tcp協(xié)議的基本內(nèi)容殴玛,主要包括一下四部分:
- tcp概述
- TCP可靠數(shù)據(jù)傳輸
- TCP流量控制
- TCP連接管理
讓我們對(duì)tcp有一個(gè)簡(jiǎn)單的回顧總結(jié)
TCP概述
- tcp是一個(gè)點(diǎn)對(duì)點(diǎn)端到端的傳輸協(xié)議,有一個(gè)發(fā)送方和接收方惑惶。
- tcp傳輸?shù)氖强煽康陌葱虻竭_(dá)的字節(jié)流
- tcp采用流水線機(jī)制作烟,提高傳輸?shù)男省CP通過(guò)擁塞控制和流量控制機(jī)制來(lái)控制滑動(dòng)窗口的大小
- tcp協(xié)議分別設(shè)置了發(fā)送方緩存和接收方緩存
- tcp采取全雙工(full-duplex)傳輸,也就是傳輸過(guò)程中珍促,同一連接可以傳輸雙向的數(shù)據(jù)流,發(fā)送方可以傳給接收方剩愧,接收方也可以傳給發(fā)送方猪叙。
- tcp是面向連接的協(xié)議,通信雙方在發(fā)送數(shù)據(jù)之前必須建立連接。連接狀態(tài)只在連接的兩端中維護(hù)穴翩,在沿途節(jié)點(diǎn)中并不維護(hù)狀態(tài)犬第。TCP連接包括:兩臺(tái)主機(jī)上的緩存、連接狀態(tài)變量芒帕、socket等
- tcp實(shí)現(xiàn)了流量控制機(jī)制
TCP段結(jié)構(gòu)
TCP: 序列號(hào)和ACK
序列號(hào):
- 序列號(hào)指的是segment中第一個(gè)字節(jié)的編號(hào)歉嗓,而不是segment的編號(hào)
- 建立TCP連接時(shí),雙方隨機(jī)選擇序列號(hào)
ACKs:
- 希望接收到的下一個(gè)字節(jié)的序列號(hào)
- 累計(jì)確認(rèn):該序列號(hào)之前的所有字節(jié)均已被正確接收到
Q: 接收方如何處理亂序到達(dá)的Segment背蟆?
- A: TCP規(guī)范中沒(méi)有規(guī)定鉴分,由TCP的實(shí)現(xiàn)者做出決策
上圖我們進(jìn)行一個(gè)分析,以便搞清楚tcp序列號(hào)和ack的應(yīng)用
首先带膀,hostA作為發(fā)送方給B發(fā)送數(shù)據(jù)志珍,隨機(jī)選擇一個(gè)序列號(hào)seq = 42,也就是這段segment中的第一個(gè)字節(jié)的編號(hào)垛叨,并且設(shè)置ack=79伦糯,這表示,希望接收方回傳seg=79作為確認(rèn)信號(hào)代表接收方已經(jīng)正確接受了這段數(shù)據(jù)
然后HostB成功接收到數(shù)據(jù)嗽元,想發(fā)送方返回確認(rèn)信息舔株,根據(jù)發(fā)送方的ack,所以確認(rèn)的seg=79还棱,然后通過(guò)ack告知希望接收到的下一個(gè)字節(jié)的序列號(hào)载慈,并同時(shí)表示之前的所有字節(jié)均已被正確接收,所以發(fā)送ack=43告知已經(jīng)接收到43號(hào)之前的字節(jié)珍手,并希望發(fā)送方傳送43號(hào)字節(jié)
TCP可靠數(shù)據(jù)傳輸
具體的可靠傳輸原理在上一篇博文中http://www.reibang.com/p/6a99944bb9fa
接下來(lái)我們看看tcp協(xié)議是如何實(shí)現(xiàn)可靠傳輸?shù)摹?/p>
- TCP在IP層提供的不可靠服務(wù)基礎(chǔ)上實(shí)現(xiàn)可靠數(shù)據(jù)傳輸服務(wù)
- 流水線機(jī)制
- 累積確認(rèn)
- TCP使用單一重傳定時(shí)器
- 觸發(fā)重傳的事件:超時(shí)和收到重復(fù)ACK
RTT和超時(shí)
問(wèn)題:如何設(shè)置定時(shí)器的超時(shí)時(shí)間办铡?
- 大于RTT, 但是RTT是變化的
- 過(guò)短:不必要的重傳
- 過(guò)長(zhǎng): 對(duì)段丟失時(shí)間反應(yīng)
問(wèn)題:如何估計(jì)RTT琳要?
SampleRTT: 測(cè)量從段發(fā)出去到收到ACK的時(shí)間忽略重傳
SampleRTT變化,測(cè)量多個(gè)SampleRTT寡具,求平均值,形成RTT的估計(jì)值EstimatedRTT
EstimatedRTT = (1- ?)EstimatedRTT + ?SampleRTT
指數(shù)加權(quán)移動(dòng)平均
典型值:0.125
TCP發(fā)送方事件
從應(yīng)用層收到數(shù)據(jù)后稚补,會(huì)進(jìn)行以下幾個(gè)步驟:
- 創(chuàng)建segment
- 序列號(hào)是segment第一個(gè)字節(jié)的編號(hào)
- 開(kāi)啟計(jì)時(shí)器
- 設(shè)置超時(shí)時(shí)間TimeOutInterval
如果發(fā)生超時(shí)事件:
- 重傳引起超時(shí)的segment
- 重啟計(jì)時(shí)器
收到ACK:
- 如果確認(rèn)此前未確認(rèn)的Segment童叠,更新SendBase,如果窗口中還有未被確認(rèn)的分組课幕,重新啟動(dòng)定時(shí)器
發(fā)送端偽碼
NextSeqNum = InitialSeqNum
SendBase = InitialSeqNum
loop (forever) {
switch(event)
event: data received from application above
create TCP segment with sequence number NextSeqNum
if (timer currently not running)
start timer
pass segment to IP
NextSeqNum = NextSeqNum + length(data)
event: timer timeout
retransmit not-yet-acknowledged segment with
smallest sequence number
start timer
event: ACK received, with ACK field value of y
if (y > SendBase) {
SendBase = y
if (there are currently not-yet-acknowledged segments)
start timer
}
} /* end of loop forever */
TCP重傳示例
快速重傳機(jī)制
TCP的實(shí)現(xiàn)中厦坛,如果發(fā)生超時(shí),超時(shí)時(shí)間間隔將重新設(shè)置乍惊,即將超時(shí)時(shí)間間隔加倍杜秸,導(dǎo)致其很大,重發(fā)丟失的分組之前要等待很長(zhǎng)時(shí)間.
通過(guò)重復(fù)ACK檢測(cè)分組丟失,Sender會(huì)背靠背地發(fā)送多個(gè)分組,如果某個(gè)分組丟失,可能會(huì)引發(fā)多個(gè)重復(fù)的ACK.
如果sender收到對(duì)同一數(shù)據(jù)的3個(gè)ACK润绎,則假定該數(shù)據(jù)之后的段已經(jīng)丟失.
快速重傳:在定時(shí)器超時(shí)之前即進(jìn)行重傳
算法
event: ACK received, with ACK field value of y
if (y > SendBase) {
SendBase = y
if (there are currently not-yet-acknowledged segments)
start timer
}
else {
increment count of dup ACKs received for y
if (count of dup ACKs received for y = 3) {
resend segment with sequence number y
}
TCP流量控制
接收方為TCP連接分配buffer
上層應(yīng)用可能處理buffer中數(shù)據(jù)的速度較慢
流量控制:發(fā)送方不會(huì)傳輸?shù)奶嗲说⑻煲灾劣谘蜎](méi)接收方(buffer溢出)
(假定TCP receiver丟棄亂序的segments)
Buffer中的可用空間(spare room)
= RcvWindow
= RcvBuffer-[LastByteRcvd -LastByteRead]
Receiver通過(guò)在Segment的頭部字段將RcvWindow 告訴Sender诞挨。 Sender限制自己已經(jīng)發(fā)送的但還未收到ACK的數(shù)據(jù)不超過(guò)接收方的空閑RcvWindow尺寸。
Receiver告知SenderRcvWindow=0,會(huì)出現(xiàn)什么情況呢蛤?
會(huì)出現(xiàn)卡死惶傻,發(fā)送方不發(fā)數(shù)據(jù)了。關(guān)于這些問(wèn)題具體會(huì)在tcp擁塞控制里面討論其障。
TCP連接管理
TCP sender和receiver在傳輸數(shù)據(jù)前需要建立連接达罗。
三次握手機(jī)制
Step 1: client host sends TCP SYN
segment to server
? specifies initial seq #
? no data
Step 2: server host receives SYN, replies
with SYNACK segment
? server allocates buffers
? specifies server initial seq. #
Step 3: client receives SYNACK, replies
with ACK segment, which may
contain data
四次握手機(jī)制
TCP連接管理:關(guān)閉
Step 1: client向server發(fā)送TCP FIN 控制segment
Step 2: server 收到FIN, 回復(fù)ACK. 關(guān)閉連接, 發(fā)送
FIN.
Step 3: client 收到FIN, 回復(fù)ACK.
? 進(jìn)入“等待” –如果收到FIN,會(huì)重新發(fā)送ACK
Step 4: server收到ACK. 連接關(guān)閉.
由于TCP連接是全雙工的静秆,因此每個(gè)方向都必須單獨(dú)進(jìn)行關(guān)閉粮揉。這原則是當(dāng)一方完成它的數(shù)據(jù)發(fā)送任務(wù)后就能發(fā)送一個(gè)FIN來(lái)終止這個(gè)方向的連接。收到一個(gè) FIN只意味著這一方向上沒(méi)有數(shù)據(jù)流動(dòng)抚笔,一個(gè)TCP連接在收到一個(gè)FIN后仍能發(fā)送數(shù)據(jù)扶认。首先進(jìn)行關(guān)閉的一方將執(zhí)行主動(dòng)關(guān)閉,而另一方執(zhí)行被動(dòng)關(guān)閉殊橙。
》觥(1) TCP客戶端發(fā)送一個(gè)FIN,用來(lái)關(guān)閉客戶到服務(wù)器的數(shù)據(jù)傳送(報(bào)文段4)膨蛮。
〉啤(2) 服務(wù)器收到這個(gè)FIN,它發(fā)回一個(gè)ACK敞葛,確認(rèn)序號(hào)為收到的序號(hào)加1(報(bào)文段5)誉察。和SYN一樣,一個(gè)FIN將占用一個(gè)序號(hào)惹谐。
〕制(3) 服務(wù)器關(guān)閉客戶端的連接,發(fā)送一個(gè)FIN給客戶端(報(bào)文段6)氨肌。
『韪选(4) 客戶段發(fā)回ACK報(bào)文確認(rèn),并將確認(rèn)序號(hào)設(shè)置為收到序號(hào)加1(報(bào)文段7)怎囚。