1. 程式人生 > >計算機網路 滑動視窗協議

計算機網路 滑動視窗協議

(i)  1位滑動視窗協議
在7.4.1節介紹的協議都假定資料幀沿著一個方向傳輸,但事實上大多數的通訊都是雙向的。當雙方都有資料傳送時,將確認序號攜帶在資料幀中傳輸可以減少開銷,這稱為捎帶應答(Piggybacking)。捎帶應答帶來的一個問題是:當需要傳送確認時沒有要傳送的資料幀怎麼辦?這可以讓確認資訊推遲一點時間再發送,如果仍然沒有資料幀要傳送,再用一個單獨的幀進行確認。本節及後面兩節將要介紹的三個協議都是用於雙向資料傳輸的協議,且都屬於滑動視窗協議,但它們的效率、複雜度及對記憶體的需求都不同。
1位滑動視窗協議使用"停-等"方式,所以只需要1位元長的幀序號。由於支援雙向傳輸,所以每個協議實體需要同時完成傳送和接收兩個功能,過程如下。
(1)初始化傳送序號和期待接收的幀序號:next_frame_to_send = 0,frame_expected = 0(next_frame_to_send指明發送方正在傳送的哪一幀,而frame_expected則指明瞭接收方正在等待的哪一幀,在1位滑動視窗協議中,這兩個值只能是"0"或者"1");
(2)從網路層接收一個分組,放入緩衝區;
(3)從緩衝區中取出分組構造一個幀,它又分為以下三個小步驟。
將緩衝區中的分組拷入幀的資訊域;
將next_frame_to_send拷入傳送序號域;
將1- frame_expected(第一個期待的幀)拷入確認序號域。
(4)對最近收到的幀確認。
(5)將幀傳給物理層,同時啟動相關的計時器;
(6)等待事件發生(幀到達,收到壞幀,超時);
(7)如果發生的事件為幀到達,則從物理層接收一個幀,首先檢查幀的seq域,若正是期待接收的幀(seq = frame_expected),則將幀中攜帶的分組交給網路層,frame_expected加1;然後檢查幀的ack域,若正是等待確認的幀(ack = next_frame_to_send),終止相關的計時器,從網路層接收一個新的分組放入緩衝區,next_frame_to_send加1,繼續執行下一步。如果發生的是其他事件(收到壞幀,超時),則也繼續進行下一步。
(8)用緩衝區中的資料分組、next_frame_to_send和1- frame_expected構造一個幀,傳給物理層,同時也啟動計時器,返回到步驟(6)。以後就重複繼續執行這樣的迴圈。

在這種1位滑動視窗協議中,在正常情況下,傳送方和接收方是交替傳送的;但當傳送方和接收方同時向對方傳送或超時設定得太短時,會造成不必要的重發,但協議也能夠正常執行。

(ii)GO-BACK-N協議的視窗機制
在前面已介紹了GO-BACK-N協議,在此繼續介紹這一協議中的視窗機制。
直到現在,我們一直假定訊號的傳播延遲可以忽略不計,但事實上有些時候是不能忽略的,比如在衛星通道上,如果通道的資料速率為b bit/s,幀的長度為l bit,訊號的來回延遲為R秒,則線路的效率為l/(l+bR)。如果我們在等待確認的時候多傳送一些幀,就可以提高線路的效率,這事實上允許傳送視窗包含多個未被確認的幀,這種技術稱為"管道化"(Pipelining)。當訊號傳播延遲遠大於幀的傳輸時間時,適合採用這個技術。
當管道化技術建立在不可靠的通道上時會有一些問題。比如,如果位於幀流中的某個幀丟失或損壞了,另外在傳送程序發現出錯前,大量的後繼幀會到達接收方;也可能當一個壞幀到達接收方時,顯然會被接收方丟棄,這些又如何處理呢?
有兩種基本的方法來處理以上問題:(1)稱之為"GO-BACK-N"協議,接收程序丟棄所有的後繼幀,並且不通知傳送程序。該策略對應接收視窗為1的情況,即只能按順序接收幀,當傳送程序超時後,必須按順序重傳所有未被確認的幀。如果錯誤率高的話,這種方法會浪費很多頻寬,但對記憶體需求不大。(2)稱之為"選擇重傳"(對應接收視窗大於1的情況),只要是落入接收視窗且校驗正確的幀,都要接收下來放到緩衝區裡,這樣當傳送程序意識到某個幀出錯時,只是重傳此幀而不是所有的後繼幀。選擇重傳通常使用NAK對校驗出錯或疑為丟失的幀進行確認,以便傳送程序儘快重傳該幀。如果第二次重傳成功,接收方的資料鏈路層中會有許多按順序排列的正確幀,這些幀可以一起交給網路層,並只對最高序號的幀進行確認。當視窗很大時,這種方法需要大量的資料鏈路層記憶體,但它不浪費頻寬。
GO-BACK-N的過程如下。
(1)初始化。
開網路層允許;
ack_expected = 0(此時處於傳送視窗的下沿);
next_frame_to_send = 0,frame_expected = 0(初始化正在傳送的幀和期待的幀序號);
nbuffered = 0(進行傳送視窗大小初始化);
(2)等待事件發生(網路層準備好,幀到達,收到壞幀,超時)。
(3)如果事件為網路層準備好,則執行以下步驟。
從網路層接收一個分組,放入相應的緩衝區;
傳送視窗大小加1;
使用緩衝區中的資料分組、next_frame_to_send和frame_expected構造幀,繼續傳送;
next_frame_to_send加1;
跳轉(7);
(4)如果事件為幀到達,則從物理層接收一個幀,則執行以下步驟。
首先檢查幀的seq域,若正是期待接收的幀(seq = frame_expected),將幀中攜帶的分組交給網路層,frame_expected加1;
然後檢查幀的ack域,若ack落於傳送視窗內,表明該序號及其之前所有序號的幀均已正確收到,因此終止這些幀的計時器,修改傳送視窗大小及傳送視窗下沿值將這些幀去掉,繼續執行步驟(7);
(5)如果事件是收到壞幀,繼續執行步驟(7)。
(6)如果事件是超時,即:next_frame_to_send = ack_expected,從發生超時的幀開始重發傳送視窗內的所有幀,然後繼續執行步驟(7)。
(7)若傳送視窗大小小於所允許的最大值(MAX-SEQ),則可繼續向網路層傳送,否則則暫停繼續向網路層傳送,同時返回互步驟(2)等待。
注:在這個協議中有一個問題,沒有考慮到當某個方向上沒有資料要傳送時,要對收到的幀進行單獨確認。在收到期待的幀後應該啟動一個ACK超時計時器,當發生超時事件時,判斷哪個計時器超時,若是ACK計時器超時,應該單獨傳送一個確認幀。而當傳送了一個數據包時,應將被捎帶確認的幀的ACK計時器終止。另外,在使用GO-BACK-N協議時,傳送視窗的大小不能超過2n-1。

(iii) 選擇性重傳協議的視窗機制
同樣,在前面我們已介紹了選擇性重傳協議,在此繼續介紹這一協議中的視窗機制。
在該協議中,傳送方的視窗大小從0開始增長到某個預定的最大值,而接收方的視窗總是保持固定大小的,並等於該最大值。接收視窗內的每個序號都有一個緩衝區,並有一位指示緩衝區是空還是滿。當一個幀到達時,只要其序號落在接收視窗內,且此前並未收到過(相應緩衝區為空),就接收此幀,並存於相應的緩衝區中;僅當序號比它小的所有幀都已遞交給了網路層,此幀才會被提交給網路層。使用選擇重發協議,傳送視窗也不能大於2n-1。
具體的選擇重發過程可以描述如下:
(1)初始化:類似GO-BACK-N的初始化,但增加了與接收視窗相關的內容,如設定接收視窗的大小、清空緩衝區滿標誌等。
(2)等待事件發生(幀到達,收到壞幀,資料幀超時,網路層準備好,ACK超時)。
(3)如果發生的事件為網路層準備好,則從網路層接收一個分組,組幀傳送,修改相關引數,與GO-BACK-N的處理方法相同,繼續執行步驟(6)。
(4)如果事件為幀到達,則從物理層接收一個幀,若為資料幀,且不是期待接收、未傳送過NAK(不應答)的幀,則傳送一個NAK幀,要求重發指定序號的幀(Frame_expected);否則啟動ACK計時器;若收到的幀落在接收視窗內,且此前未收到過,則放入相應緩衝區並設定緩衝區滿標誌;若接收視窗下沿幀已經到達,則從該幀開始將連續的若干個幀交給網路層,並修改相應引數(緩衝區滿標誌,接收視窗範圍),啟動ACK計時器。
若為NAK幀,且請求重發的幀落在當前的傳送視窗內,則重發這個幀。若從傳送視窗下沿開始連續的若干個幀已被確認,則終止這些幀的計時器,修改傳送視窗大小及傳送視窗下沿值將這些幀去掉;繼續執行下一步。
(5)如果發生的事件為收到壞幀,則在尚未傳送過NAK時,傳送一個NAK,繼續執行步驟(6);如果發生的事件為超時(資料幀超時),重發超時的幀,也繼續執行步驟(6);如果事件為ACK超時,為指定的幀傳送單獨的確認幀,同樣繼續執行步驟(6)。
(6)若傳送視窗大小小於所允許的最大值(NR_BUFS),則允許繼續向網路層傳送幀,否則暫停向網路層繼續傳送幀,返回到步驟(2),繼續等待