生活随笔
收集整理的這篇文章主要介紹了
NS3系列—3———NS3中文:4 概念描述
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
http://www.cnblogs.com/lovemo1314/archive/2011/02/12/1951867.html
NS3中文:4 概念描述
4 ?概念概述(Conceptual Overview) ??????????????????????? http://www.nsnam.org/docs/release/tutorial/tutorial_16.html#Conceptual-Overview | 翻譯:陳杰 ?? 劉小洋 | piyajee@163.com? (百思論壇 ) |
| 校稿: Xiaochuan Shen | xcs105@zepler.net |
| 編輯: ProbibidoAmor | banana.0420@yahoo.com.cn |
4.1 ?關(guān)鍵的抽象概念(Key Abstractions) 在本節(jié)中,我們將回顧一些常用的網(wǎng)絡(luò)術(shù)語,以及它們?cè)?/span>ns-3 的特定含義。 4.1.1 節(jié)點(diǎn) 在因特網(wǎng)術(shù)語中,任何一臺(tái)連接到網(wǎng)絡(luò)的計(jì)算設(shè)備被稱為主機(jī),亦稱為終端。 ns -3是一個(gè)網(wǎng)絡(luò)模擬器,而非一個(gè)專門的因特網(wǎng)模擬器,為此我們避開術(shù)語“主機(jī)”,因?yàn)檫@個(gè)詞太容易讓人聯(lián)想到因特網(wǎng)和及其相關(guān)協(xié)議。因此,我們選用了一個(gè)來源于圖論,在其他網(wǎng)絡(luò)模擬器中亦廣泛使用的術(shù)語:節(jié)點(diǎn)。 ns-3中基本計(jì)算設(shè)備被抽象為節(jié)點(diǎn)。節(jié)點(diǎn)由C++中的Node類來描述。Node類提供了用于管理仿真器中網(wǎng)絡(luò)組件表示的各種方法。 你應(yīng)該將節(jié)點(diǎn)設(shè)想為一臺(tái)可以添加各種功能的計(jì)算機(jī)。為了使一臺(tái)計(jì)算機(jī)有效地工作,我們可以給它添加應(yīng)用程序,協(xié)議棧,外設(shè)卡及驅(qū)動(dòng)程序等。NS3 采用了與此相同的模型。 4.1.2 Application 4.1.2 應(yīng)用程序 計(jì)算機(jī)軟件通常可分為兩大類:系統(tǒng)軟件和應(yīng)用軟件。系統(tǒng)軟件根據(jù)計(jì)算模型配置和管理計(jì)算機(jī)中的各種資源,例如內(nèi)存,處理器周期,硬盤,網(wǎng)絡(luò)等。系統(tǒng)軟件通常并不直接使用這些資源來完成用戶任務(wù)。用戶往往需要運(yùn)行應(yīng)用程序來完成一些特定的任務(wù),而應(yīng)用程序需要使用由系統(tǒng)軟件控制的資源。 通常,系統(tǒng)軟件和應(yīng)用軟件的界線表現(xiàn)為特權(quán)級(jí)的變化,而這種變化是通過操作系統(tǒng)的自陷功能(operating system traps)來實(shí)現(xiàn)的。在ns-3中并沒有真正的操作系統(tǒng)的概念,更沒有特權(quán)級(jí)別或者系統(tǒng)調(diào)用的概念。然而,我們有應(yīng)用程序的概念。正如“現(xiàn)實(shí)世界”中在計(jì)算機(jī)上運(yùn)行應(yīng)用程序以執(zhí)行各種任務(wù)一樣,ns-3仿真環(huán)境中的應(yīng)用程序在節(jié)點(diǎn)上運(yùn)行來驅(qū)動(dòng)模擬過程。 在ns-3中,需要被仿真的用戶程序被抽象為應(yīng)用。應(yīng)用在C++中用Application類來描述。這個(gè)類提供了管理仿真時(shí)用戶層應(yīng)用的各種方法。開發(fā)者應(yīng)當(dāng)用面向?qū)ο蟮姆椒ㄗ远x和創(chuàng)建新的應(yīng)用。在本教程中,我們會(huì)使用Application類的實(shí)例:UdpEchoClientApplication 和UdpEchoServerApplication。也許你已經(jīng)猜到了,這些應(yīng)用程序包含了一個(gè)client/server應(yīng)用來發(fā)送和回應(yīng)仿真網(wǎng)絡(luò)中的數(shù)據(jù)包。 4.1.3 信道 在現(xiàn)實(shí)世界中,人們可以把計(jì)算機(jī)連接到網(wǎng)絡(luò)上。通常我們把網(wǎng)絡(luò)中數(shù)據(jù)流流過的媒介稱為信道。當(dāng)你把以太網(wǎng)線插入到墻壁上的插孔時(shí),你正通過信道將計(jì)算機(jī)與以太網(wǎng)連接。在ns-3的模擬環(huán)境中,你可以把節(jié)點(diǎn)連接到代表數(shù)據(jù)交換信道的對(duì)象上。在這里,基本的通信子網(wǎng)這一抽象概念被稱為信道,在C++中用Channel類來描述。 Channel類提供了管理通信子網(wǎng)對(duì)象和把節(jié)點(diǎn)連接至它們的各種方法。信道類同樣可以由開發(fā)者以面向?qū)ο蟮姆椒ㄗ远x。一個(gè)信道實(shí)例可以模擬一條簡(jiǎn)單的線纜(wire),也可以模擬一個(gè)復(fù)雜的巨型以太網(wǎng)交換機(jī),甚至無線網(wǎng)絡(luò)中充滿障礙物的三維空間。 我們?cè)诒窘坛讨袑⑹褂脦讉€(gè)信道模型的實(shí)例,包括:CsmaChannel, PointToPointChannel和WifiChannel。舉例來說,CsmaChannel信道模擬了用于一個(gè)可以實(shí)現(xiàn)載波偵聽多路訪問通信子網(wǎng)中的媒介。這個(gè)信道具有和以太網(wǎng)相似的功能。 4.1.4 網(wǎng)絡(luò)設(shè)備 以前,如果想把一臺(tái)計(jì)算機(jī)連接到網(wǎng)絡(luò)上,你就必須買一根特定的網(wǎng)絡(luò)線纜,并在你的計(jì)算機(jī)上安裝稱為外設(shè)卡的硬件設(shè)備。能夠?qū)崿F(xiàn)網(wǎng)絡(luò)功能的外接卡被稱為網(wǎng)絡(luò)接口卡(網(wǎng)卡)。現(xiàn)在大多數(shù)計(jì)算機(jī)出廠時(shí)已經(jīng)配置了網(wǎng)卡,所以用戶看不到這些的模塊。 一張網(wǎng)卡如果缺少控制硬件的軟件驅(qū)動(dòng)是不能工作的。在Unix(或者Linux)系統(tǒng)中,外圍硬件被劃為 “設(shè)備”。設(shè)備通過驅(qū)動(dòng)程序來控制,而網(wǎng)卡通過網(wǎng)卡驅(qū)動(dòng)程序來控制。在Unix和Linux系統(tǒng)中,網(wǎng)卡被稱為像eth0這樣的名字。 在ns-3中,網(wǎng)絡(luò)設(shè)備這一抽象概念相當(dāng)于硬件設(shè)備和軟件驅(qū)動(dòng)的總和。NS3仿真環(huán)境中,網(wǎng)絡(luò)設(shè)備相當(dāng)于安裝在節(jié)點(diǎn)上,使得節(jié)點(diǎn)通過信道和其他節(jié)點(diǎn)通信。像真實(shí)的計(jì)算機(jī)一樣,一個(gè)節(jié)點(diǎn)可以通過多個(gè)網(wǎng)絡(luò)設(shè)備同時(shí)連接到多條信道上。 網(wǎng)絡(luò)設(shè)備由C++中的NetDevice類來描述。NetDevice類提供了管理連接其他節(jié)點(diǎn)和信道對(duì)象的各種方法,并且允許開發(fā)者以面向?qū)ο蟮姆椒▉碜远x。我們?cè)诒窘坛讨袑⑹褂脦讉€(gè)特定的網(wǎng)絡(luò)設(shè)備的實(shí)例,它們分別是CsmaNetDevice, PointToPointNetDevice, 和 WifiNetDevice。正如以太網(wǎng)卡被設(shè)計(jì)成在以太網(wǎng)中工作一樣,CsmaNetDevice被設(shè)計(jì)成在csma信道中工作,而PointToPointNetDevice 在PointToPoint信道中工作,WifiNetNevice在wifi信道中工作。 ? 4.1.5 拓?fù)渖善?/span> ? ?? 在現(xiàn)實(shí)的網(wǎng)絡(luò)中,你會(huì)發(fā)現(xiàn)主機(jī)已裝有(或者內(nèi)置)的網(wǎng)卡。在 ns-3 中你會(huì)發(fā)現(xiàn)節(jié)點(diǎn)附加了網(wǎng)絡(luò)設(shè)備。在大型仿真網(wǎng)絡(luò)中,你需要在節(jié)點(diǎn)、網(wǎng)絡(luò)設(shè)備和信道之間部署許多連接。 既然把網(wǎng)絡(luò)設(shè)備連接到節(jié)點(diǎn)、信道,配置IP地址等等事情在ns-3是很普遍是任務(wù),那么我們干脆提供了“拓?fù)渖善?/span>”來使這個(gè)工作變得盡可能的容易。舉例來說:創(chuàng)建一個(gè)網(wǎng)絡(luò)設(shè)備,配置一個(gè)MAC地址,把此網(wǎng)絡(luò)設(shè)備裝載到節(jié)點(diǎn)上,設(shè)置節(jié)點(diǎn)的協(xié)議棧,以及連接網(wǎng)絡(luò)設(shè)備到一個(gè)信道,這些事情都需要許多分立的ns-3核心操作。而當(dāng)需要把許多設(shè)備連接到多點(diǎn)信道,在網(wǎng)際間將單個(gè)網(wǎng)絡(luò)進(jìn)行連接,則需要對(duì)ns-3核心進(jìn)行更多更多的分立操作。我們提供了拓?fù)渖善鱽碚线@些大量分立的步驟,使其成為一個(gè)簡(jiǎn)單易用的操作。很明顯,這樣做可以極大地方便用戶。 ? 4.2 第一個(gè)ns-3腳本 如果你按照前面所述下載了ns3仿真系統(tǒng),你會(huì)發(fā)現(xiàn)在你的根目錄下的“repos”的文件夾里有一份ns-3的發(fā)行版。進(jìn)入那個(gè)目錄,你可以看到一個(gè)如下的文件目錄: ? 進(jìn)入examples/tutorial目錄。你會(huì)發(fā)現(xiàn)一個(gè)叫first.cc的文件。這一個(gè)腳本會(huì)在兩個(gè)節(jié)點(diǎn)間創(chuàng)建一個(gè)簡(jiǎn)單的點(diǎn)到點(diǎn)的連接,并且在這兩個(gè)節(jié)點(diǎn)之間傳送一個(gè)數(shù)據(jù)包。讓我們一行一行的分析一下這個(gè)腳本,下面就用你鐘愛的編輯器打開first.cc吧。 4.2.1 ?樣本 在文件中的第一行是emacs模式行。這行告訴了emacs我們?cè)谠创a中使用的預(yù)定格式(代碼風(fēng)格) ?/* -*- Mode:C++; c-file-style:''gnu''; indent-tabs-mode:nil; -*- */ 這向來是一個(gè)有點(diǎn)爭(zhēng)議的主題,所以我們不妨現(xiàn)在就把它提出來。像許多大型的軟件開發(fā)項(xiàng)目一樣,ns-3項(xiàng)目采用了一套所有貢獻(xiàn)代碼必須遵守的代碼風(fēng)格。如果你想給ns-3貢獻(xiàn)代碼,你最終需要遵守在文件doc/codingstd.txt中說明的或者遵守在ns-3項(xiàng)目的網(wǎng)頁here上顯示的代碼標(biāo)準(zhǔn)。 我們建議你在使用ns-3的代碼的時(shí)候最好適應(yīng)這個(gè)標(biāo)準(zhǔn)。所有的開發(fā)團(tuán)隊(duì)和貢獻(xiàn)者帶著不同程度的抱怨來做到了這一點(diǎn)。如果你使用emacs編輯器的話,emacs模式行會(huì)使代碼格式符合規(guī)范更加容易。 Ns-3仿真器使用了 GNU General Public License許可。你會(huì)在 ns-3的每一個(gè)文件頭看到相應(yīng)的 GNU法律條文。通常你會(huì)在 GPL內(nèi)容的上方看到一個(gè)相關(guān)機(jī)構(gòu)的版權(quán)聲明,而在 GPL內(nèi)容的下方會(huì)有相應(yīng)的作者列表。 /* ?? * This program is free software; you can redistribute it and/or modify ?? * it under the terms of the GNU General Public License version 2 as ?? * published by the Free Software Foundation; ?? * ?? * This program is distributed in the hope that it will be useful, ?? * but WITHOUT ANY WARRANTY; without even the implied warranty of ?? * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.? See the ?? * GNU General Public License for more details. ?? * ?? * You should have received a copy of the GNU General Public License ?? * along with this program; if not, write to the Free Software ?? * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA? 02111-1307 USA ?? */ 4.2.2 模塊包含 代碼一般是以一系列的include聲明開始的: ? #include "ns3/core-module.h" ? #include "ns3/simulator-module.h" ? #include "ns3/node-module.h" ? #include "ns3/helper-module.h" 為了幫助高層的腳本用戶處理大量的系統(tǒng)中的include文件,我們把所有的包含文件,根據(jù)模塊功能,進(jìn)行了大致的分類。我們提供了一個(gè)單獨(dú)的include文件,這個(gè)文件會(huì)遞歸加載所有會(huì)在每個(gè)模塊中會(huì)被使用的include文件。我們給你提供了按大致功能分類的一組include文件,在使用時(shí)只需選擇包含這幾個(gè)包含文件(include文件),而非考慮復(fù)雜的依賴關(guān)系,在尋找所需要的頭文件上花費(fèi)不必要的時(shí)間。這不是最有效地方法但很明顯讓編寫腳本文件容易多了。 在編譯的過程中,每一個(gè)ns-3的include文件被放在build目錄下一個(gè)叫ns3的目錄中,這樣做可以避免include文件名的沖突。ns3/core-module.h與src/core目錄下的ns-3模塊相對(duì)應(yīng)。如果你查看ns3目錄會(huì)發(fā)現(xiàn)大量的頭文件。當(dāng)你編譯時(shí),Waf會(huì)根據(jù)配置把在ns3目錄下的公共的頭文件放到build/debug 或者build/optimized目錄下。Waf也會(huì)自動(dòng)產(chǎn)生一個(gè)模塊include文件來加載所有的公共頭文件。 當(dāng)然,既然你一步步遵循著這個(gè)手冊(cè)走的話,你可能已經(jīng)使用過如下命令: ? ./waf -d debug configure 來配置工程以完成調(diào)試工作。你可能同樣使用了如下命令: ? ./waf 來編譯ns-3。現(xiàn)在如果你進(jìn)入http://www.cnblogs.com/build/debug/ns3 目錄的話你會(huì)發(fā)現(xiàn)本節(jié)開頭提到的四個(gè)頭文件。你可以仔細(xì)看一下這些文件的內(nèi)容,你會(huì)發(fā)現(xiàn)它們包含了在相關(guān)模塊中的所有的include文件。 ? 4.2.3 Ns3 Namespace 在first.cc腳本的下一行是namespace的聲明。 ? using namespace ns3; Ns-3工程是在一個(gè)叫做 ns3的 C++ 命名空間中實(shí)現(xiàn)的。這把所有與 ns3相關(guān)的聲明,集中在一個(gè)與全局命名空間相區(qū)別的命名空間中。我們希望這樣會(huì)給 ns3與其他代碼的集成帶來好處。 C++用“使用”語句( using)來把 ns-3 namespace引入到當(dāng)前的(全局的)聲明域中。這個(gè)聲明就是說,你不用為了使用 ns-3的代碼而必須在所有的 ns-3代碼前打上 ns3:: 作用域操作符。如果你對(duì)命名空間并不熟悉, 請(qǐng)查閱任何的 C++ 手冊(cè)并比較 ns3 命名空間和標(biāo)準(zhǔn) ”std” 命名空間的使用;通常你可以在 cout和 streams的討論中看到命名空間的相關(guān)部分。 4.2.4 日志 下一句腳本如下: NS_LOG_COMPONENT_DEFINE ("FirstScriptExample"); 我們認(rèn)為本節(jié)是談?wù)?span style="font-family:Times New Roman">Doxygen 文件系統(tǒng)的好地方。如果你查看ns-3項(xiàng)目的網(wǎng)站(ns-3 project),你會(huì)在導(dǎo)航欄中發(fā)現(xiàn)一個(gè)指向“Doxygen (ns-3-dev)” 的鏈接。打開鏈接,你會(huì)被帶到當(dāng)前開發(fā)版文檔頁面。同時(shí)還有一個(gè)“Doxygen (stable)”得鏈接,它是最新的ns-3穩(wěn)定發(fā)行版的文檔頁面。 在左邊,你能找到一個(gè)文檔結(jié)構(gòu)的圖形化目錄。在ns-3的導(dǎo)航樹中NS-3 Modules這本 “書”是一個(gè)開始的好地方。如果你展開“Modules”目錄會(huì)看到ns-3 模塊文件的列表。這里的“模塊”一級(jí)中的內(nèi)容和上面討論的模塊include文件中的內(nèi)容一一對(duì)應(yīng)。Ns-3的日志子系統(tǒng)是核心模塊(core module)的一部分,所以繼續(xù)前進(jìn)打開核心(Core)這個(gè)文件節(jié)點(diǎn)。接著展開調(diào)試(“Debugging”)節(jié)點(diǎn),選擇日志(Logging)頁面。 ? ??? ? 你現(xiàn)在應(yīng)該看一下日志模塊的Doxygen文件。在頁面頂上的#defines列表中你會(huì)看到NS_LOG_COMPONENT_DEFINE的條目。在你想要要深入了解之前,最好仔細(xì)看看日志模塊的詳細(xì)說明,這樣你能夠了解一下總體的流程。你可以繼續(xù)下拉或者選擇在collaboration diagram下的“更多”鏈接來達(dá)到目的。 一旦對(duì)日志模塊有了整體的概念,那么請(qǐng)仔細(xì)看針對(duì)? NS_LOG_COMPO-NENT_DEFINE的文檔。我不想把整個(gè)文件復(fù)制到這里,但是可以總結(jié)一下大致的意思,這一行聲明了一個(gè)叫FirstScriptExample的日志構(gòu)件,通過引用FirstScriptExample這個(gè)名字的操作,可以實(shí)現(xiàn)打開或者關(guān)閉控制臺(tái)日志的輸出。 ? 4.2.5 ?Main Function 下面的腳本是: ??? int ? main (int argc, char *argv[]) ? { 這就是你的腳本程序的主函數(shù)的聲明。正如任何其它C++程序一樣,你需要定義一個(gè)會(huì)被第一個(gè)執(zhí)行的主函數(shù)。你的ns-3腳本沒有什么特別的,就和一個(gè)普通的C++程序一樣。 下面兩行腳本是用來使兩個(gè)日志組件生效的。它們被內(nèi)建在Echo Client 和Echo Server 應(yīng)用中: ??? LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO); LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO); 如果你已經(jīng)讀過了日志組件文檔,你會(huì)看到日志分成一系列詳盡級(jí)別。這兩行代碼將回顯clients和server的日志級(jí)別設(shè)為”INFO”級(jí)。這樣,當(dāng)仿真發(fā)生數(shù)據(jù)包發(fā)送和接受時(shí),對(duì)應(yīng)的應(yīng)用就會(huì)輸出相應(yīng)的日志消息 關(guān)于日志模塊,我們?cè)诤罄m(xù)內(nèi)容中會(huì)詳細(xì)介紹。現(xiàn)在我們直接著手創(chuàng)建拓?fù)浜瓦\(yùn)行仿真。我們使用拓?fù)渖善鲗?duì)象來使這件事盡可能的容易。 4.2.6拓?fù)渖善?/strong> 4.2.6.1 使用NodeContainer類 在我們的腳本中的下面兩行將會(huì)創(chuàng)建ns-3節(jié)點(diǎn)對(duì)象,它們?cè)诜抡嬷写碛?jì)算機(jī)。 ??? NodeContainer nodes; nodes.Create (2); 在繼續(xù)之前我們先找到NodeContainer類的文檔。進(jìn)入一個(gè)現(xiàn)成的類的說明文檔可以通過在Doxygen頁面的類標(biāo)簽中做到。如果你沒有關(guān)閉上一節(jié)中打開的Doxygen頁面的話,只要上拉到頁面的頂部并選擇類標(biāo)簽,就可以看見一個(gè)新的標(biāo)簽,類列表,出現(xiàn)。在標(biāo)簽下面你看看到所有的ns-3的類列表。往下翻,找到ns3::NodeContainer。當(dāng)你找到它后,點(diǎn)擊它然后進(jìn)入這個(gè)類的說明文檔。 你可能回憶起節(jié)點(diǎn)概念是我們的一個(gè)關(guān)鍵抽象概念。節(jié)點(diǎn)代表一臺(tái)能夠加入諸如協(xié)議棧,應(yīng)用以及外設(shè)卡等等的東西的計(jì)算機(jī)。NodeContainer 的拓?fù)渖善魈峁┮环N簡(jiǎn)便的方式來創(chuàng)建、管理和使用任何節(jié)點(diǎn)對(duì)象,我們用這些節(jié)點(diǎn)來運(yùn)行模擬器。上面的第一行只是聲明了一個(gè)名為”nodes”的NodeContainer。第二行調(diào)用了nodes對(duì)象的Create()方法創(chuàng)建了兩個(gè)節(jié)點(diǎn)。正如Doxygen所描述的那樣,這個(gè)容器調(diào)用NS-3種的內(nèi)部函數(shù)來產(chǎn)生兩個(gè)節(jié)點(diǎn)對(duì)象,并把指向這兩個(gè)對(duì)象的指針存儲(chǔ)在系統(tǒng)之中。 在腳本中他們所代表的節(jié)點(diǎn)什么都沒有做。構(gòu)建拓?fù)涞南乱徊绞前盐覀兊墓?jié)點(diǎn)連接到一個(gè)網(wǎng)絡(luò)中。我們所支持的最簡(jiǎn)單的網(wǎng)絡(luò)形式是一個(gè)在兩個(gè)節(jié)點(diǎn)之間單獨(dú)的point-to-point連接。我們?cè)诖藭?huì)構(gòu)建一個(gè)此類連接。 4.2.6.2 使用PointToPointHelper類 現(xiàn)在我們來以一種你以后將會(huì)非常熟悉的方式來構(gòu)建一個(gè)點(diǎn)到點(diǎn)的連接。我們使用拓?fù)渖善鱽硗瓿蓜?chuàng)建,連接的底層工作。回憶一下我們的兩個(gè)關(guān)鍵抽象概念:網(wǎng)絡(luò)設(shè)備、信道。在真實(shí)的世界中,這些東西大致相當(dāng)于外設(shè)卡和網(wǎng)線。需要說明的是這兩樣?xùn)|西緊密的聯(lián)系在一起而不能夠把它們交互地使用(比如以太網(wǎng)設(shè)備和無線信道就不能一起使用)。拓?fù)渖善髯裱诉@種緊密的連接,因此你在這個(gè)腳本中僅需使用PointToPointHelper來配置和連接ns-3的PointToPointNetDevice和PointToPointChannel對(duì)象。 在腳本中下面的三句話是: ??? PointToPointHelper pointToPoint; ??? pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms")); 其中第一行, PointToPointHelper pointToPoint; 在棧中初始化了一個(gè)PointToPointHelper的對(duì)象PointToPoint。而緊接著的下一行, pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); 從上層的角度告訴PointToPointHelper對(duì)象當(dāng)創(chuàng)建一個(gè)PointToPointNetDevice對(duì)象時(shí)使用“5Mbps"來作為數(shù)據(jù)速率。 ? 從細(xì)節(jié)方面講,字符串“DataRate”與PointToPointNetDevice的一個(gè)屬性相對(duì)應(yīng)。如果你查看Doxygen中的ns3::PointToPointNetDevice 類,并閱讀GetTypeId 方法的文檔,你會(huì)發(fā)現(xiàn)設(shè)備定義了一系列屬性,在這些屬性中就有“DataRate”。大部分用戶可見的ns-3對(duì)象都有類似的屬性列表。正如你在下面的部分會(huì)看到的一樣,我們使用了這個(gè)機(jī)制以方便地配置仿真器,而不用重新對(duì)源代碼進(jìn)行編譯。 與PointToPointNetDevice上的“DataRate”類似,PointToPointChannel也有一個(gè)Delay屬性: ?pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms")); 告訴PointToPointHelper使用"2ms"(2毫秒)作為每一個(gè)被創(chuàng)建的點(diǎn)到點(diǎn)信道傳輸延時(shí)值。 4.2.6.3 使用NetDeviceContainer類 現(xiàn)在我們有一個(gè)包含兩個(gè)節(jié)點(diǎn)的NodeContainer對(duì)象。我們有一個(gè)準(zhǔn)備在兩個(gè)節(jié)點(diǎn)之間創(chuàng)建PointToPointNetDevices和wirePointToPointChannel對(duì)象的PointToPointHelper對(duì)象。正如我們使用NodeContainer拓?fù)渖善鲗?duì)象來為我們的模擬創(chuàng)建節(jié)點(diǎn),我們會(huì)讓PointToPointHelper來做關(guān)于創(chuàng)建,配置和安裝設(shè)備的工作。我們需要一個(gè)所有被創(chuàng)建的NetDevice對(duì)象列表,所以我們使用一個(gè)NetDeviceContainer對(duì)象來存放它們,就像我們使用一個(gè)NodeContainer對(duì)象來存放我們所創(chuàng)建節(jié)點(diǎn)。下面兩行代碼: ??? NetDeviceContainer devices; devices = pointToPoint.Install (nodes); 會(huì)完成設(shè)備和信道的配置。第一行聲明了上面提到的設(shè)備容器,第二行完成了主要工作。PointToPointHelper的Install()方法以一個(gè)NodeContainer對(duì)象作為一個(gè)參數(shù)。在Install()方法內(nèi),一個(gè)NetDeviceContainer被創(chuàng)建了。對(duì)于在NodeContainer 對(duì)象中的每一個(gè)節(jié)點(diǎn)(對(duì)于一個(gè)點(diǎn)到點(diǎn)鏈路必須明確有兩個(gè)節(jié)點(diǎn)),一個(gè)PointToPointNetDevice被創(chuàng)建和保存在設(shè)備容器內(nèi)。一個(gè)PointToPointChannel對(duì)象被創(chuàng)建,兩個(gè)PointToPointNetDevices與之連接。當(dāng)PointToPointHelper對(duì)象創(chuàng)建時(shí),那些在生成器中就被預(yù)先地設(shè)置的屬性被用來初始化對(duì)象對(duì)應(yīng)的屬性值。 當(dāng)調(diào)用了pointToPoint.Install(nodes)后,我們會(huì)有兩個(gè)節(jié)點(diǎn),每一個(gè)節(jié)點(diǎn)安裝了點(diǎn)到點(diǎn)網(wǎng)絡(luò)設(shè)備,在它們之間是一個(gè)點(diǎn)到點(diǎn)信道。兩個(gè)設(shè)備會(huì)被配置在一個(gè)有2毫秒傳輸延時(shí)的信道上以5M比特每秒的速率傳輸數(shù)據(jù)。 4.2.6.4 使用InternetStackHelper類 我們現(xiàn)在已經(jīng)配置了節(jié)點(diǎn)和設(shè)備,但是我們還沒有在節(jié)點(diǎn)上安裝任何協(xié)議棧。下面兩行代碼完成這個(gè)任務(wù): ??? InternetStackHelper stack; ??? stack.Install (nodes); 類InternetStackHelper 是一個(gè)安裝PointToPointHelper 對(duì)象和點(diǎn)到點(diǎn)網(wǎng)絡(luò)設(shè)備的網(wǎng)絡(luò)協(xié)議棧的拓?fù)渖善黝悺F渲?/span>Install()方法以一個(gè)NodeContainer 對(duì)象做為一個(gè)參數(shù),當(dāng)它被執(zhí)行后,它會(huì)為每一個(gè)節(jié)點(diǎn)容器中的節(jié)點(diǎn)安裝一個(gè)網(wǎng)絡(luò)協(xié)議棧(TCP,UDP,IP等等)。 4.2.6.5 使用Ipv4AddressHelper類 下面我們需要為節(jié)點(diǎn)上的設(shè)備設(shè)置IP地址。我們也提供了一個(gè)拓?fù)渖善鱽砉芾?span style="font-family:Times New Roman">IP地址的分配。當(dāng)執(zhí)行實(shí)際的地址分配時(shí)唯一用戶可見的API是設(shè)置基IP地址和子網(wǎng)掩碼。 在我們的范例腳本文件first.cc的下兩行代碼 ??? Ipv4AddressHelper address; address.SetBase ("10.1.1.0", "255.255.255.0"); 聲明了一個(gè)地址生成器對(duì)象,并且告訴它應(yīng)該開始從10.1.1.0開始以子網(wǎng)掩碼為255.255.255.0分配地址。地址分配默認(rèn)是從1開始并單調(diào)的增長(zhǎng),所以在這個(gè)基礎(chǔ)上第一個(gè)分配的地址會(huì)是10.1.1.1,緊跟著是10.1.1.2等等。底層ns-3系統(tǒng)事實(shí)上會(huì)記住所有分配的IP地址,如果你無意導(dǎo)致了相同IP地址的產(chǎn)生,這將是一個(gè)致命的錯(cuò)誤(順便說一下,這是個(gè)很難調(diào)試正確的錯(cuò)誤)。 ? ? 下面一行代碼, ? Ipv4InterfaceContainer interfaces = address.Assign (devices); 完成了真正的地址配置。在ns-3中我們使用 Ipv4Interface對(duì)象將一個(gè)IP地址同一個(gè)設(shè)備關(guān)聯(lián)起來。正如我們有時(shí)候需要一個(gè)被生成器創(chuàng)建的網(wǎng)絡(luò)設(shè)備列表一樣,我們有時(shí)候需要一個(gè) Ipv4Interface對(duì)象的列表。Ipv4InterfaceContainer提供了這樣的功能。 現(xiàn)在我們有了一個(gè)安裝了協(xié)議棧,配置了IP地址類的點(diǎn)到點(diǎn)的網(wǎng)絡(luò)。這時(shí)我們所要做的事情是運(yùn)用它來產(chǎn)生數(shù)據(jù)通信。 4.2.7 Applications類 另一個(gè)ns-3系統(tǒng)的核心抽象是Application類。在這個(gè)腳本中我們用兩個(gè)特定的ns-3核心 Application類:UdpEchoServerApplication和UdpEchoClientApplication。正如我們先前聲明過的一樣,我們使用生成器對(duì)象來幫助配置和管理潛在的對(duì)象。在這里,我們用UdpEchoServerHelper 和 UdpEchoClientHelper 對(duì)象使我們的工作更加容易點(diǎn)。 4.2.7.1 UdpEchoServerHelper類 下面在first.cc腳本中的代碼被用來在我們之前創(chuàng)建的節(jié)點(diǎn)上設(shè)置一個(gè)UDP 回顯服務(wù)應(yīng)用。 ??? UdpEchoServerHelper echoServer (9); ??? ApplicationContainer serverApps = echoServer.Install (nodes.Get (1)); ??? serverApps.Start (Seconds (1.0)); serverApps.Stop (Seconds (10.0)); 上面一片代碼中的第一行聲明了UdpEchoServerHelper。像往常一樣,這個(gè)并非應(yīng)用本身,這是一個(gè)用來幫助創(chuàng)建真正應(yīng)用的對(duì)象。我們約定在生成器中放置必需的屬性。本例中,除非我們告知生成器服務(wù)器和客戶端所共知的一個(gè)端口號(hào),否則這個(gè)生成器是不會(huì)起任何作用的。我們并沒有隨機(jī)選擇,而是把這個(gè)端口號(hào)作為生成器構(gòu)造函數(shù)的一個(gè)參數(shù)。只要你愿意,你就能夠使用 SetAttribute設(shè)置“Port”參數(shù)到另一個(gè)值。 同其它生成器對(duì)象類似,UdpEchoServerHelper對(duì)象有一個(gè)Install方法。實(shí)際上是這個(gè)方法的執(zhí)行,才初始化回顯服務(wù)器的應(yīng)用,并將應(yīng)用連接到一個(gè)節(jié)點(diǎn)上去。有趣的是,安裝方法把NodeContainter當(dāng)做一個(gè)參數(shù),正如我們看到的其他安裝方法一樣。這里有一個(gè)C++隱式轉(zhuǎn)換,此轉(zhuǎn)換以nodes.Get(1)的結(jié)果作為輸入,并把它作為一個(gè)未命名的NodeContainer的構(gòu)造函數(shù)的參數(shù),最終這個(gè)未命名的NodeContainer被送入Install 方法中去 。如果你曾迷失于在 C++ 代碼中找到一個(gè)編譯和運(yùn)行良好的特定方法簽名( signature ),那么就尋找這些內(nèi)在的轉(zhuǎn)換。 我們現(xiàn)在會(huì)看到echoServer.Install將會(huì)在管理節(jié)點(diǎn)的NodeContainer容器索引號(hào)為1的機(jī)節(jié)點(diǎn)上安裝一個(gè)UdpEchoServerApplication。安裝會(huì)返回一個(gè)容器,這個(gè)容器中包含了指向所有被生成器創(chuàng)建的應(yīng)用指針。 應(yīng)用對(duì)象需要一個(gè)時(shí)間參數(shù)來“開始”產(chǎn)生數(shù)據(jù)通信并且可能在一個(gè)可選的時(shí)間點(diǎn)“停止”。我們提供了開始和停止的兩個(gè)參數(shù)。這些時(shí)間點(diǎn)是用ApplicationContainer的方法Start和Stop來設(shè)置的。這些方法以”Time”對(duì)象為參數(shù)。在這種情況下,我們使用了一種明確的C++轉(zhuǎn)換序列來獲得C++雙精度(double)的1.0并且用一個(gè)Seconds轉(zhuǎn)換(cast)來把它轉(zhuǎn)換到ns-3的Time對(duì)象。需要注意的是轉(zhuǎn)換規(guī)則是模型的作者所控制,并且C++也有它自己的標(biāo)準(zhǔn),所以你不能總是假定參數(shù)會(huì)按照你的意愿順利地轉(zhuǎn)換。下面兩行, ??? serverApps.Start (Seconds (1.0)); ??? serverApps.Stop (Seconds (10.0)); 會(huì)使echo服務(wù)應(yīng)用在1s時(shí)開始(生效)并在10s時(shí)停止(失效)。既然我們已經(jīng)聲明了一個(gè)模擬事件(就是應(yīng)用的停止事件)在10s時(shí)被執(zhí)行,模擬至少會(huì)持續(xù)10s。 4.2.7.2 UdpEchoClientHelper類 echo客戶端應(yīng)用的設(shè)置與回顯服務(wù)器端類似。也有一個(gè) UdpEchoClientHelper來管理 UdpEchoClientApplication。 ??? UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9); ??? echoClient.SetAttribute ("MaxPackets", UintegerValue (1)); ??? echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.))); ??? echoClient.SetAttribute ("PacketSize", UintegerValue (1024)); ??? ApplicationContainer clientApps = echoClient.Install (nodes.Get (0)); ??? clientApps.Start (Seconds (2.0)); ??? clientApps.Stop (Seconds (10.0)); 然而,對(duì)于echo客戶端,我們需要設(shè)置五個(gè)不同的屬性。首先兩個(gè)屬性是在UdpEchoClientHelper的構(gòu)建過程中被設(shè)置的。按照生成器的構(gòu)造函數(shù)的格式,我們把”RemoteAdress”和”RemotePort”屬性傳遞給了生成器(實(shí)際上是作為生成器構(gòu)造函數(shù)的兩個(gè)必須參數(shù)傳遞的)。 回憶一下我們使用Ipv4InterfaceContainer來追蹤我們配置給設(shè)備的IP地址。在界面容器中位置零的界面對(duì)象將會(huì)和在節(jié)點(diǎn)容器中的位置零的節(jié)點(diǎn)對(duì)象對(duì)應(yīng)。同樣在界面容器中位置一的界面對(duì)象將會(huì)和在節(jié)點(diǎn)容器中的位置一的節(jié)點(diǎn)對(duì)象對(duì)應(yīng)。所以,在上面的第一行代碼中,我們創(chuàng)建了一個(gè)生成器并告訴它設(shè)置客戶端的遠(yuǎn)端地址為服務(wù)器節(jié)點(diǎn)的IP地址。我們同樣告訴它準(zhǔn)備發(fā)送第二個(gè)數(shù)據(jù)包到端口9。 那個(gè)“MaxPackets”屬性告訴客戶端我們所允許它在模擬期間所能發(fā)送的最大數(shù)據(jù)包個(gè)數(shù)。“Interval”屬性告訴客戶端在兩個(gè)數(shù)據(jù)包之間要等待多長(zhǎng)時(shí)間,而“PacketSize”屬性告訴客戶端它的數(shù)據(jù)包應(yīng)該承載多少數(shù)據(jù)。本例中,我們讓客戶端發(fā)送一個(gè)1024字節(jié)的數(shù)據(jù)包。 正如echo服務(wù)端一樣,我們告訴echo客戶端何時(shí)來開始和停止,但是這里我們使客戶端在服務(wù)端生效1s后才開始(在模擬器中時(shí)間2s的時(shí)候)。 ? 4.2.8 Simulator類 下面我們所需要做的就是運(yùn)行模擬器,這是用全局函數(shù)Simulator::Run.來做到的 ??? Simulator::Run (); 當(dāng)我們調(diào)用了如下方法時(shí): ??? serverApps.Start (Seconds (1.0)); ??? serverApps.Stop (Seconds (10.0)); ??? ... ??? clientApps.Start (Seconds (2.0)); ??? clientApps.Stop (Seconds (10.0)); ? 實(shí)際上我們是在模擬器中1.0秒,2.0秒,和10.0時(shí)預(yù)設(shè)了時(shí)間的發(fā)生。當(dāng)Simulator::Run被調(diào)用時(shí),系統(tǒng)會(huì)開始遍歷預(yù)設(shè)事件的列表并執(zhí)行。首先它會(huì)在1.0s時(shí)運(yùn)行事件,這個(gè)事件會(huì)使echo服務(wù)端應(yīng)用生效(這個(gè)事件會(huì)預(yù)設(shè)更多的其他事件)。接下來仿真器會(huì)運(yùn)行在t=2.0秒時(shí)的事件,即讓echo客戶端應(yīng)用開始。同樣的,這個(gè)事件可能會(huì)預(yù)定更多的其他事件。在echo客戶端應(yīng)用中的開始事件的執(zhí)行會(huì)通過給服務(wù)端傳送一個(gè)數(shù)據(jù)包來開始仿真的數(shù)據(jù)傳送階段。 發(fā)送一個(gè)數(shù)據(jù)包給服務(wù)端會(huì)引發(fā)一系列更多的事件。這些事件會(huì)被預(yù)設(shè)在此事件之后,并根據(jù)我們已經(jīng)在腳本中設(shè)定的時(shí)間參數(shù)來執(zhí)行數(shù)據(jù)包的應(yīng)答。 其實(shí),我們只發(fā)送了一個(gè)數(shù)據(jù)包(回憶一MaxPackets屬性被設(shè)置為一),在此之后,那個(gè)被單獨(dú)的客戶端應(yīng)答請(qǐng)求所引發(fā)的連鎖反應(yīng)會(huì)停止,并且模擬器會(huì)進(jìn)入空閑狀態(tài)。當(dāng)這發(fā)生時(shí),生下來的事件就是服務(wù)端和客戶端的Stop事件。當(dāng)這些事件被執(zhí)行后,就沒有將來的事件來執(zhí)行了,函數(shù)Simulator::Run會(huì)返回。整個(gè)模擬過程就結(jié)束了。 ? ? 下面剩下的事情就是清理了。這個(gè)通過調(diào)用全局函數(shù)Simulator::Destroy來完成。當(dāng)生成器函數(shù)(或者低級(jí)的ns-3代碼)被執(zhí)行后,生成器安排的鉤子函數(shù)就被插入到模擬器中來銷毀所有被創(chuàng)建的對(duì)象。你自己并不需要追蹤任何對(duì)象,你所需要做的僅僅是調(diào)用Simulator::Destroy并且退出。ns-3系統(tǒng)會(huì)幫你料理這些繁雜的任務(wù)。在first.cc腳本中剩下的代碼如下: ??? Simulator::Destroy (); ??? return 0; ? } 4.2.9 ?創(chuàng)建自己的腳本 我們已經(jīng)讓構(gòu)建你自己的腳本變得非常省事。你所需要做的僅僅是把你的腳本放到scratch目錄下,并運(yùn)行waf,這樣你的腳本就會(huì)被編譯。在回到高層目錄后復(fù)制examples/tutorial/first.cc到scratch目錄下 ? cd .. ? cp examples/tutorial/first.cc scratch/myfirst.cc 現(xiàn)在使用waf命令來創(chuàng)建自己的第一個(gè)實(shí)例腳本: ? ./waf 你應(yīng)該可以看到消息報(bào)告說你的myfirst范例被成功編譯了。 ? Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' ? [614/708] cxx: scratch/myfirst.cc -> build/debug/scratch/myfirst_3.o ? [706/708] cxx_link: build/debug/scratch/myfirst_3.o -> build/debug/scratch/myfirst ? Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' ? 'build' finished successfully (2.357s) 現(xiàn)在你能夠運(yùn)行這個(gè)例子(注意如果你在scratch目錄編譯了你的程序,你必須在scratch目錄外運(yùn)行它): ? ./waf --run scratch/myfirst 你應(yīng)該能看到一些輸出: ? Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' ? Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' ? 'build' finished successfully (0.418s) ? Sent 1024 bytes to 10.1.1.2 ? Received 1024 bytes from 10.1.1.1 ? Received 1024 bytes from 10.1.1.2 這里你看到編譯系統(tǒng)核查來確定文件被編譯了,接著運(yùn)行了它。你看到在echo日志構(gòu)件顯示了它已經(jīng)發(fā)送了1024字節(jié)到在10.1.1.2的echo服務(wù)端。還可以看到回顯服務(wù)器端的日志構(gòu)件顯示他從10.1.1.1接收到了1024字節(jié)。接下來echo服務(wù)端應(yīng)答了數(shù)據(jù)包,你能看到echo客戶端記錄了它已經(jīng)接收到了從服務(wù)端發(fā)送過來的回顯數(shù)據(jù)包。
總結(jié)
以上是生活随笔為你收集整理的NS3系列—3———NS3中文:4 概念描述的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。