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