傳輸層
- 傳輸層
- 可靠傳輸層模型
- TCP詳解
- 連接的具體含義(The TCP Connection)
- TCP 結構(TCP Segment Structure)
- TCP Sequence Numbers and Acknowledgment Numbers
- TCP 的重傳機制(Round-Trip Time Estimation and Timeout)
- 書上作者認為的一些“有趣的場景”(┗( ▔, ▔ )┛)
- TCP的快速重傳
- TCP的流量控制(flow control)
- TCP連接管理(TCP Connection Management)
- TCP擁塞控制( Principles of Congestion Control)
- 書上的TCP擁塞控制
可靠傳輸層模型
RDT1.0
-
-
信賴底層協議,認為底層協議是可靠的,但是實際上底層協議IP層是不可靠協議
RDT 2.0
-
在1.0的基礎上加上了
ARQ (Automatic Repeat reQuest) protocols
ACK :positive acknowledgments
NAK :negative acknowledgments
-
ARQ包括:
-
錯誤校驗(Error detection.):
和UDP的checksum一樣,需要額外的位(extra bits)來做校驗
-
接受者的回復(Receiver feedback)
a 0 value could indicate a NAK and a value of 1 could indicate an ACK.
-
重新發送(Retransmission)
接受有錯的包將會重新由sender發送
-
-
有限狀態機分析(FSM)
-
sender:
兩個狀態,一個是等待上層喚起(rdt_send(data))
接着制作發送的包(sndpkt=make_pkt(data,checksum))
最后發送該包(udt_send(sndpkt))
這里的udt是指的UDP-based Data Transfer Protocol嗎?
接着進入第二個狀態,等待ACK和NAK的狀態
收到received packet並且檢驗是否為NAK(rdt_rcv(rcvpkt)&&isNAK(rcvpkt))
如果是就重復該狀態
否則回到第一個狀態(rdt_rcv(rcvpkt)&&isACK(rcvpkt))
-
receiving side
一個狀態
如果有錯,就制作一個NAK的包發過去
否則就解析、傳遞數據給對應進程,並且制作一個ACK的包發過去
-
-
特點:
-
sender只有在確認接收方得到了數據包之后才會發一下個,所以這種發送方式也被稱為
stop-and-wait
協議(Thus, the sender will not send a new piece of data until it is sure that the receiver has correctly received the current packet. Because of this behavior, protocols such as rdt2.0 are known as stop-and-wait protocols.)
-
RDT2.0依然有問題,主要在於沒有考慮到ACK和NCK包也可能會出問題
哪怕是加了校驗位也很難,因為你只知道有問題,但不知道怎么復原
(The more difficult question is how the protocol should recover from errors in ACK or NAK packets.)
解決方式有幾種:
-
加入一種新的包來讓對方重新發送(即,“我妹聽清楚”)
(thus introducing a new type of sender-to-receiver packet to our protocol)
-
加入足夠多的校驗位,讓我們不僅能夠知道錯了,還能知道哪里錯了
-
第三種就是發送方收到一個錯誤的ACK包或NAK包(garbled ACK or NAK)時,只是重新發送當前數據包。這樣做會引發新的問題,接收方不知道這個是新的包還是舊的包,可能會有數據的冗余出現
-
第四種方法,就是在基於stop-and-wait協議上用一個1-bit的序列號(sequence number)來標記是否為重復發送,這就是RDT2.1
-
-
RDT2.1
-
有限狀態機分析(FSM)
-
sender
- 先等待上層協議喚起一個等待0 的狀態,制作一個帶有序列號0 ,數據data,校驗和checksum的包,用udt_send 發送【第一個狀態】
- 接着轉為一個等待0序列的ACK和NAK【第二個狀態】
- 如果是ACK包或NAK包有corrupt或返回的是一個NAK包,就重新發送原來的sndpkt
- 否則就進入一個等待上層協議喚起等待1的狀態,喚起后制作一個帶有序列號1,數據data,校驗和checksum的包,用udt_send發送【第三個狀態】
- 接着轉為一個等待序列1的ACK或NAK【第四個狀態】
- 反復重復
-
receiver
-
【狀態一】接收方有兩個狀態,接收方先等待一個0序列包,
如果是包有錯誤,就發送一個NAK消息給sender
如果是包沒有錯誤,但是收到的是一個1序列包,就說明sender是沒有聽清楚我的確認消息,重新發送了之前的包,由於stop-and-wait,我一定是接收到正確的包之后才會發生狀態轉換,所以這個1序列包已經是我接收過的了,所以我發送一個ACK包回去,並且繼續等待我的0號包
如果包沒有錯誤,並且收到的是一個0序列包,就解析,傳遞數據,並且返回ACK包
進入第二個等待1的狀態
-
【狀態二】對稱地重復上面的內容
-
-
RDT2.2
-
RDT2.2是一種不用NAK的協議(NAK-free protocol),使用ACK+序列號來解決問題(duplicate ACK at sender results in same action as NAK :retransmit current pkt)
-
有限狀態機分析(FSM)
-
sender
-
淦,差不多的,不想寫了
-
-
RDT3.0
-
RDT 2.* 只考慮了數據包出現位錯誤的問題( corrupting bits),沒有考慮丟包的(lose packets)問題(雖然不常見)
-
RDT 3.0引入了timer,一個計時器來解決丟包的問題
-
也被叫做交替位協議(alternating-bit protocol)
-
有限狀態機分析
-
sender
主要改進就是,在發送了一個sndpkt之后,會有一個start_timer 的動作,設置一個計時器
如果收到的確認包有錯或者是ACK+不期待的序列號,那么就繼續等待,直到timeout超時了還沒有的話,就重新發送,並且同時重置start_timer,即每次發送了sndpkt之后都會重置計時器的。
-
receiver和RDT2.2就是一樣的了
-
-
RDT3.0存在的問題
-
這是一個功能上完善但是性能上不能令人滿意的協議,主要就是他的stop-and-wait的協議
-
書上的圖:
-
沒有出問題時的情況:
-
出問題了:
【lost packet】發送的包在中途丟失,接收方自然不會發送確認信息,發送方等到超時后重發
【lost ACK】發送方收不到確認ACK包,就等到超時之后重發原包,因為和接收方的序列號不一致,接收方知道是已經收到過的,就丟棄
【premature timeout】接收方的ACK包延時了,收到的時候已經超時了,但是因為序列號的緣故,亂序並不會影響
-
-
pipelined sending
-
-
上圖是pipeline和阻塞式的對比
可以看到,阻塞式的信道利用率是
\[(L/R)/(L/R+RTT) \]而pipeline的利用率是阻塞式的三倍
\[(L/R)*3/(L/R+RTT) \] -
為了做到pipeline,我們需要在這RDT3.0的基礎上繼續添加內容
- 增加序列號
- 實現緩存
Go-Back-N (GBN)
-
從左往右:
已經ACK了的,
已經發送,但是沒ACK的,
准備好了,還沒發送的,
還沒准備好的
即:base是最老的那個發了還沒ACK的
nextseqnum是即將發送的
-
-
GBN的問題
- 主要是累計確認和全部重發,會在當窗口大小和帶寬延遲都比較大的時候,很多包可能在管道中,因此,一個數據包錯誤就可能導致GBN重新傳輸大量的數據包,這是不必要的
- 於是我們又引入了
selective-repeat
來解決這一問題
-
selective-repeat(SR)
-
TCP詳解
連接的具體含義(The TCP Connection)
- the connection is a logical one
- 【客戶端】套接字剛剛創建完成的時候,里面並沒有存放任何數據,也不知道通 信的對象是誰。在這個狀態下,即便應用程序要求發送數據,協議棧也不 知道數據應該發送給誰。瀏覽器可以根據網址來查詢服務器的 IP 地址,而 且根據規則也知道應該使用 80 號端口,但只有瀏覽器知道這些必要的信息 是不夠的,因為在調用 socket 創建套接字時,這些信息並沒有傳遞給協議 棧。因此,我們需要把服務器的 IP 地址和端口號等信息告知協議棧,這是連接操作的目的之一
- 【服務器端】那么,服務器這邊又是怎樣的情況呢?服務器上也會創建套接字 A,但 服務器上的協議棧和客戶端一樣,只創建套接字是不知道應該和誰進行通 信的。而且,和客戶端不同的是,在服務器上,連應用程序也不知道通信 對象是誰,這樣下去永遠也沒法開始通信。於是,我們需要讓客戶端向服 務器告知必要的信息,比如“我想和你開始通信,我的 IP 地址是 xxx.xxx. xxx.xxx,端口號是 yyyy。”可見,客戶端向服務器傳達開始通信的請求, 也是連接操作的目的之一。
- 【連接的具體含義】
- 連接實際上是通信雙方交換控制信息,在套接字中記 錄這些必要信息並准備數據收發的一連串操作
- 此外,當執行數據收發操作時,我們還需要一塊用來臨時存放 要收發的數據的內存空間,這塊內存空間稱為緩沖區,它也是在連接操作 的過程中分配的。上面這些就是“連接”B 這個詞代表的具體含義。
- A TCP connection provides a
full-duplex service
:
TCP 結構(TCP Segment Structure)
-
-
從上到下,從左到右:
-
發送方端口號:16bits
-
接收方端口號:16bits
-
序列號【發送數據的序列編號】:32bits(發送方告知接收方該網絡包發送的數據相當於所有發送數據的第幾個字節)
-
ACK號【接受數據的順序編號】:32bits(接收方告知發送方已經收到了所有數據的第幾個字節)
-
數據偏移量【頭部的長度】:4bits
-
保留位:4bits
-
控制位:6bits
-
窗口號:16bits【接收方告知發送方窗口大小(即無需等待確認可一起發送的數據量)
-
校驗和:16bits
-
緊急指針:16bits
-
可選字段:可變長度
-
TCP Sequence Numbers and Acknowledgment Numbers
- 每一個TCP段的序列號是該段的第一個字節占字節流的第幾個字節(The sequence number for a segment is therefore the byte-stream number of the first byte in the segment.)
- TCP is
full-duplex
這意味着,主機A到主機B可能在同一個TCP連接上,同時有發送數據和接收數據, - 所以發送的ACK號,是希望收到的一下個序列號(The acknowledgment number that Host A puts in its segment is the sequence number of the next byte Host A is expecting from Host B.)
- TCP只接收自己希望的,所以TCP是累計確認(cumulative acknowledgments)
TCP 的重傳機制(Round-Trip Time Estimation and Timeout)
-
估計RTT時間
-
先通過統計學采樣獲取sampleRTT
-
之后用權值,將其和歷史sampleRTT結合得到estimateRTT
EstimatedRTT=(1-α)*EstimatedRTT +α * SampleRTT
α通常取值為0.25
-
為了不讓RTT變化過於劇烈,加上一個偏差:
DevRTT= (1- β)*DevRTT + β * |SampleRTT -EstimatedRTT |
通暢來說,β取值為0.25
-
最后得到的延時時間應該為:
\[TimeoutInterval = EstimatedRTT +4 * DevRTT \]
-
-
思考:
We have discussed TCP's estimation of RTT, Why do you think TCP avoid measuring the SampleRTT for retransmitted segments?
【答】:重傳情況下,RTT可能會有很大的偏差,比如,0號段的ACK在路上堵車了,超時沒有收到,sender重發,然后這時之前堵車的ACK來了,在sender看來,他是無法區分這個ACK到底是之前發的,還是重發返回的ACK,在sender眼里,就是我剛剛重發,馬上就有響應了,所以RTT會大幅度的縮短。所以沒有意義。
書上作者認為的一些“有趣的場景”(┗( ▔, ▔ )┛)
-
【返回包丟失的情況】
上圖中,A向B發送了一個序列號為92,長度為8的TCP段:
92 93 94 95 96 97 98 99 主機B向A確認,並返回期望拿到的序列號:ACK100,這個包在路上走丟了
主機A等待超時之后重傳該包即可
-
【兩次超時】
上圖中主要的特殊在於,在sender重發了第一個段(92)之后,接收方沒有返回ACK100,而是返回的ACK120,因為receiver的base指針已經累計增加到了120,他知道自己120之前的都已經接受了,只需要孜孜不倦的向sender問后面的內容即可。
-
【沒有名字】
在上圖中,receiver始終孜孜不倦的請求自己認為自己需要的,而不管sender到底怎么理解,
sender接收到ACK120之后,sender心里明白,receiver是一定拿到了92-99,才會發給自己ACK120的,【TCP的累計確認】。所以sender就直接將base滑動到120。避免了冗余的重復包發送。
TCP的快速重傳
-
接收方發送ACK,更實際的情況下,有四種情況:
事件 TCP接收方的處理方式 正常情況,接收到順序收到的TCP段,並且之前的都acknowledged了 接收方會delayed ACK,將其掛起500ms,之后再發送。這樣的好處是少發點ACK包,假設在這段時間里有其他正常收到的TCP段,根據剛剛說的,sender心里明白receiver是累計接收的,所以只需要發最后一個ACK包即可 收到一個正常的TCP段,並且有一個正常的ACK在掛起 直接發送ACK包 有比期望序號更大的段到達 馬上發送一個我期望的ACK包過去(為什么) 有能部分或者完全填充gap的段到達 如果該報段是間隔的低端,就立刻發送ACK -
上圖說明了上表中的第三種情況。一旦有亂序的段送過來,就立刻反復嘮叨自己真正想要的包
一旦sender接受到三個重復的包,就會立馬重傳。
【為什么快速重傳是選擇3次ACK?】
分包的丟失要看是鏈路故障還是亂序
兩次duplicate ACK時,要讓sender立馬重發,(而不是等到timeout了之后),那得是丟包了
接收方嘰嘰喳喳的duplicate ACK越多,就說明越可能是丟包,但是還是要考慮一個響應策略的速度,不能等到接收方苦口婆心喊了你媽幾十次才反應
根據統計規律,三次duplicate ACK時立刻重新發送是極好的。
TCP的流量控制(flow control)
-
流量控制根本原因在於,接收方的應用層不會一直擱這兒處理這個進程,如果人家半天沒理睬你,然后發送方還一直發送一直發送,接收方就只能受不了了。(•́へ•́╬)
(Recall that the hosts on each side of a TCP connection set aside a receive buffer for the connection. When the TCP connection receives bytes that are correct and in sequence, it places the data in the receive buffer. The associated application process will read data from this buffer, but not necessarily at the instant the data arrives. Indeed, the receiving application may be busy with some other task and may not even attempt to read the data until long after it has arrived. If the application is relatively slow at reading the data, the sender can very easily overflow the connection’s receive buffer by sending too much data too quickly.)
-
處理方法就是在兩邊交流,接收方告知發送方,我的緩存還剩多少
-
區分流量控制(flow control)與擁塞控制(congestion control)
(As noted earlier, a TCP sender can also be throttled due to congestion within the IP network; this form of sender control is referred to as congestion control, a topic we will explore in detail in Sections 3.6 and 3.7. Even though the actions taken by flow and congestion control are similar (the throttling of the sender), they are obviously taken for very different reasons.)
-
細節:
-
在receiver的應用層,定義了兩個變量:
LastByteRead
:應用層讀取的最后一個字節的序號LastByteRcvd
從網絡層讀取的最后一個字節,放在緩沖區的什么地方為了不讓緩沖區溢出,我們需要:
\[LastByteRcvd−LastByteRead≤RcvBuffer \] -
而TCP報文中的receive window,則表示了接收方的緩沖區還剩了多少空間:
\[rwnd=RcvBuffer−[LastByteRcvd−LastByteRead] \] 如果我妹搞錯的話,應該就像這樣:
-
而發送端則需要保證:
\[LastByteSent−LastByteAcked≤rwnd \] -
最后討論一個問題:
如果在某次通訊中,接收方給發送方告知,rwnd=0,那sender如何重啟發送呢?
【答】: 當rwnd=0時,sender會有兩種情況繼續發送數據:
- 緊急數據( urgent data )
- 試探性的發送一個字節的數據過去,看receiver返回的ACK中的rwnd是多少
-
TCP連接管理(TCP Connection Management)
-
TCP兩次握手
【為什么TCP兩次握手不行的情況】
歸根結底,就是你不知道對面是否建立連接了,沒有確認這一個部分
-
TCP三次握手
-
第一步:client host sends TCP SYN segment to server
- 發送一個初始的序列號
- 沒有帶數據
- 第二步:server host receives SYN,replies with SYNACK segment
- 服務器創建buffers
- 發送自己的初始序列號
- 如果沒有什么反饋,就重傳,如果重傳多次(一般三次)害不理我,就毀掉套接字
- 第三步: client receives SYNACK ,replies with ACK segment
- 可帶數據也可以不帶數據
-
過程
【問題】
-
為什么服務器返回的ack=client_isn+1?
【答】:因為當SYNbit=1時,TCP默認為收到一個字節
-
為什么要用隨機序列號?
> 【答】: TCP是一個有狀態協議,A與B之間有一個TCP連接,C想搞破壞,於是想偽造A的IP給B發一個Reset,要分兩種情景: > > **情景一:C處於A與B之間流量的路徑上** > C可以捕獲到A、B的IP包,偽造是小菜一碟,比如大防火牆reset用戶連接 > > **情景二:C不在A與B之間流量的路徑上** > C可以在世界的任何角落,偽造一個合法TCP報文,最關鍵是TCP字段里的sequence number 、acknowledged number,只要這兩項位於接收者滑動窗口內,就是合法的,對方可以接收並Reset A、B之間的TCP連接。 > > 而TCP握手采用隨機序列號(**不完全隨機,而是隨着時間流逝而線性增長,到了2^32盡頭再回滾**),為的就是讓攻擊者更難以猜測sequence number,因為偽造的sequence number不在合法范圍內,而被接收方丟棄,增加安全性。
-
-
TCP四次揮手
-
第一步:client end system sends TCP FIN control segment to server
-
第二步:server receives FIN ,replies with ACK ,Closes connection ,sends FIN
-
第三步: client receives FIN ,replies with ACK
-
第四步: server,receives ACK ,connection closed
-
注意下圖,一個是關閉時間,貌似和書上上面的圖不太一樣,但是應該是server等到接收到最后一個ack再close,client等到wait完了之后再close
還有一個就是server在發送FIN之前依然能夠接收數據的
-
【同樣還有一個問題,為什么要等待兩個segment 的life time?】
> 這最主要是因為兩個理由:
>
> 1、為了保證客戶端發送的最后一個ACK報文段能夠到達服務器。因為這個ACK有可能丟失,從而導致處在LAST-ACK狀態的服務器收不到對FIN-ACK的確認報文。服務器會超時重傳這個FIN-ACK,接着客戶端再重傳一次確認,重新啟動時間等待計時器。最后客戶端和服務器都能正常的關閉。假設客戶端不等待2MSL,而是在發送完ACK之后直接釋放關閉,一但這個ACK丟失的話,服務器就無法正常的進入關閉連接狀態。
>
> 2、他還可以防止已失效的報文段。客戶端在發送最后一個ACK之后,再經過經過2MSL,就可以使本鏈接持續時間內所產生的所有報文段都從網絡中消失。從保證在關閉連接后不會有還在網絡中滯留的報文段去騷擾服務器。
>
> 注意:在服務器發送了FIN-ACK之后,會立即啟動超時重傳計時器。客戶端在發送最后一個ACK之后會立即啟動時間等待計時器。
-
上課講的一道題
TCP擁塞控制( Principles of Congestion Control)
-
發生擁塞的幾種情況
-
【場景一】
-
假設路由器buffer無限
-
因為路由器buffer無限,所以不會有數據丟失,所以在C/2之前,λ(in)和λ(out)程線性
-
到C/2之后,之前學過,
\[queuing delay=La/R \]所以queuing delay會很大
-
-
【場景二】
-
路由器buffer變成了有限的
-
所以有TCP的重傳,所以真實進入網絡的是λ'
-
我們繼續分兩種情況討論
-
第一種情況,理想情況,主機能夠知道路由器的buffer情況 ,就和上面場景一差不多
-
第二種情況,知道包丟失了,TCP才重傳,不會出現早熟
在接近R/2時,就可能會出現分組丟失了,所以out就開始大於in
-
第三種情況,真實情況,也可能會出現早熟
-
-
能得到擁塞的另外的一些壞處:
- 會導致更多的、不必要的重傳
-
-
【場景三】
-
-
擁塞的其他危害:
下游路由器丟棄分組,導致上游白發送了,浪費了帶寬
-
-
-
擁塞控制的方法:
-
端到端控制,(end-end congestion control)
通過端系統對丟包,重發的觀察,猜測中間節點的情況,進行控制
TCP采用的這種控制方法
-
網絡輔助控制(network-assisted congestion control)
路由器會給終端以反饋
single bit indicating congestion (SNA, DECbit , TCP/IP ECN ATM)
explicit rate sender
-
-
擁塞控制的例子
- ATM。。。TMD 不聽了
書上的TCP擁塞控制
-
沒聽課了,看下書就是了
-
【擁塞控制和流量控制的區別】
流量控制:如果發送方把數據發送得過快,接收方可能會來不及接收,這就會造成數據的丟失。
TCP的流量控制是利用滑動窗口機制實現的,接收方在返回的數據中會包含自己的接收窗口的大小,以控制發送方的數據發送。
擁塞控制:擁塞控制就是防止過多的數據注入到網絡中,這樣可以使網絡中的路由器或鏈路不致過載。
兩者的區別:流量控制是為了預防擁塞。如:在馬路上行車,交警跟紅綠燈是流量控制,當發生擁塞時,如何進行疏散,是擁塞控制。流量控制指點對點通信量的控制。而擁塞控制是全局性的,涉及到所有的主機和降低網絡性能的因素。
-
TCP流量控制的方法:
have each
sender
limit the rate at which it sends traffic into itsconnection as a function of perceived network congestion.
這樣會帶來三個問題:
- First, how does a TCP sender limit the rate at which it sends traffic into its connection? (如何限制速率)
- Second, how does a TCP sender perceive that there is congestion on the
path between itself and the destination?發送方如何感知到擁塞 - third, what algorithm should the sender use to change its send rate as a function of perceived end-to-end congestion?如何通過感知到的擁塞來改變發送
-
問題一:如何限制速率