1. 程式人生 > >廣播路由演算法: 如何優雅地傳遞悄悄話?

廣播路由演算法: 如何優雅地傳遞悄悄話?

640?wx_fmt=gif

640?wx_fmt=jpeg

作者 | 帥地

責編 | 仲培藝

對於廣播,我相信在現實生活中我們時常都能接觸到,例如學校一言不合就響起了校歌,搞的全校人都能夠聽到,想假裝沒聽到都不行。

假如我們把學校比作一個區域網的話,某臺主機發起了一個廣播,意味著區域網內的其他所有主機都會收到這個廣播,那發起廣播的主機是如何選擇路徑來給其他主機發送廣播分組的呢?考慮下面由幾個節點組成的網路:

640?

假如節點 R1 要做一個廣播給 R2, R3, R4 發廣播分組,顯然,一種很簡單的方法就是 R1 給 R2、R3、R4 三個節點分別發一次廣播分組,這意味著 R1 一共要傳送三次同樣的廣播分組。

640?

途中不同箭頭的顏色表示 R1 給不同的節點發廣播分組。

大家想一個問題:這種傳送方式合理嗎?

是的,這種傳送方式在實現上很簡單,源節點(R1)每次帶上目的節點的地址,然後傳送給它就行了。

不過這種方式在效率上是極低的,例如,R1 傳送的這三個廣播分組都會經過同一段鏈路(R1-R2這段鏈路),而且 R2 要是再連線上 n 個節點的話,代表著這 R1 需要再發送 n 次廣播分組,這 n 個報文也會經過同一段鏈路。


640?wx_fmt=png

解決方法


為了解決這個問題,我們或許可以這樣做:R1 把廣播分組發給它的鄰居節點 R2,然後 R1 就不管了,R2 再把報文傳送給它的所有鄰居節點 R3、R4 (除了從其接收該分組的那個鄰居 R1)。

640?

顯然這種方式也是挺不錯的,R1 只發送了一次廣播分組,而且 R1-R2 這段鏈路也不會出現同一個廣播分組重複經過的情況。


640?wx_fmt=png

廣播風暴


不過,這種給所有鄰居節點發送廣播分組的方式夠優雅嗎?

看下面的一個網路組成:

640?

按照剛才的方法,R1 會給 R2 傳送廣播分組,接著 R2 會給 R3、R4 傳送廣播分組。剛才我們說過,收到廣播分組的節點會給它的所有鄰居傳送報文(除了從其接受到該報文的那個鄰居)。

所以這個時候 R3 會給 R4 傳送廣播分組文,而 R4 接收到 R3 的廣播分組之後,R4 會給 R2 傳送廣播分組,R2 收到 R4 的廣播分組之後 ,也會給 R3 再次傳送廣播分組…..

如果節點中形成了一個圈,那麼就會像上面那樣,節點之間不停傳送廣播分組,這時網路上充斥著大量重複的廣播分組,將會嚴重影響資源的利用。

我們也把這種情況稱之為廣播風暴


640?wx_fmt=png

控制廣播風暴


因此,我們必須想出某種策略來控制這種廣播風暴。

一種很簡單的方法,就是給這一份廣播分組做一個標記。例如,源節點(發起廣播的節點)可以將其地址以及廣播序號放入這個廣播分組中,然後傳送給它的所有鄰居節點,每個節點會維護它已經收到的、轉發的源地址和廣播分組的序號列表。

當節點收到一個廣播分組時,會檢查這個廣播分組是否之前接收過(可以通過源地址、報文序號來檢查),如果接收過,就把該廣播分組丟棄;否則,把該廣播分組接收,且向所有鄰居節點轉發。

例如對於下面由 7 個節點組成的網路:

640?

如果節點 A 要做一個廣播,那麼 A 就會給其鄰居節點 B、C 發一份廣播分組,B、C 也會給其的鄰居節點發送一個廣播分組。意味著 B 會給 C、D 傳送廣播分組,而 C 也會給 B、E、F 傳送一份廣播分組:

640?

當 B 收到 C 發給它的報文時,B 檢測到已經有了該報文,所以 B 會丟棄 C 傳送給它的廣播分組,C 也一樣會丟棄 B 傳送給它的廣播分組。圖中青色的箭頭代表該廣播分組會被丟棄。

640?

從圖中不難看出,就算節點之間形成了圈,也不會出現節點之間迴圈轉發的情況。

雖然該方法簡單 ,但確實有效控制了廣播風暴,當然,這只是控制廣播風暴的方法之一,實際上還有其他方法,在此我就不說了。


640?wx_fmt=png

生成樹廣播


雖然上面那種方法有效控制了廣播風暴,但也存在著很多冗餘廣播分組(那些被丟棄的廣播分組就是冗餘的廣播分組)。

640?

如果可以,我想讓每個節點僅接收一次廣播分組,也不用考慮丟棄廣播分組,所以理想的情況應該是這樣:

640?

有沒有一種方法,可以讓廣播分組像上面這種情況來傳送呢?請大家看下面一個圖:

640?

如果把節點當作一個圖的頂點,大家觀察下左邊的圖與右邊的圖有什麼聯絡。

右邊的圖不就是左邊圖的生成樹嗎?(學了這麼多年的生成樹,終於用到了),如果我們給每一段鏈路加上相應的費用,那麼我們最理想的情況就是找到一顆最小生成樹。

所以,我們最理想的情況就是讓廣播報文在最小生成樹的路徑中傳送,於是 ,我們現在的問題就是找出這些節點組成的網路中的最小生成樹。

那麼,如何構造一顆生成樹呢?下面提供一種基於中心某個中心的方法來建立一顆生成樹。注意,是生成樹,不是最小生成樹。

該方法是這樣的:我們先選出一箇中心節點,然後其他節點向這個中心節點發送加入樹報文,加入樹報文經過的路徑,都會被嫁接到生成樹上。例如對於這個網路結構:

640?

我們選擇 E 為中心點,然後其他節點給 E 傳送加入樹報文:

1. F 節點給 E 傳送加入樹報文,此時 E-F 鏈路成為初始生成樹,如下圖(紅色路徑表示生成樹)。

640?

2. 接著 B 給 E 傳送加入樹報文,假設 B 經過的路徑是 B->D->E。此時路徑 B-D-E 也加入了生成樹。

640?

注:D 不用再發送加入樹報文了,因此它此時已經在生成樹裡了。

3. 接著 C 給 E 傳送加入樹報文,C-E 加入生成樹。

640?

4. 接著,A 給 E 傳送報文,假設 A 選擇的路徑是 A->C->E。不過當 A 的報文到達 C 之後,由於原本 C-E 就在生成樹裡面了,所以 A 的報文不用經過 C-E,A-C 就加入到生成樹了。

640?

5. 最後 G 通過 D 加入生成樹。

640?

到此,生成樹構建完畢,此時生成樹如下:

640?

然後在廣播的時候,就可以沿著這條路徑來轉發複製廣播報文了。

作者:帥地,一個熱愛程式設計的在校生,我的世界不只有coding,還有writing。目前維護訂閱號「苦逼的碼農」,專注於寫演算法與資料結構、Java、計算機網路。

宣告:本文為作者個人投稿,版權歸其所有。



 熱 文 推 薦 

☞ 恆大賈躍亭和解;快播處罰細節曝光;天津三星工廠關閉 | 極客頭條

☞ 頻頻霸榜的 Python,竟遭開發者嫌棄!

☞ 遇上瀏覽器跨域問題怎麼辦?

☞ 無業務不技術:那些誓用區塊鏈重塑的行業,發展怎麼樣了?

☞ 下一次 IT 變革:邊緣計算(Edge computing)

☞ 12306 脫庫 410 萬用戶資料究竟從何洩漏?

☞ 年度重磅:《AI聚變:2018年優秀AI應用案例TOP 20》正式釋出

☞ 老程式設計師肺腑忠告:千萬別一輩子靠技術生存!


  

print_r('點個好看吧!');
var_dump('點個好看吧!');
NSLog(@"點個好看吧!");
System.out.println("點個好看吧!");
console.log("點個好看吧!");
print("點個好看吧!");
printf("點個好看吧!\n");
cout << "點個好看吧!" << endl;
Console.WriteLine("點個好看吧!");
fmt.Println("點個好看吧!");
Response.Write("點個好看吧!");
alert("點個好看吧!")
echo "點個好看吧!"

640?wx_fmt=gif點選“閱讀原文”,開啟 CSDN App 閱讀更貼心!

640?wx_fmt=png 喜歡就點選“好看”吧!