ns-3 網絡模擬器教程。 第4章

ns-3 網絡模擬器教程。 第4章
第 1,2 章
第3章

4 概念概述
4.1 關鍵抽象
4.1.1 節點
4.1.2 應用
4.1.3 頻道
4.1.4 網路設備
4.1.5 拓樸助手
4.2 第一個 ns-3 腳本
4.2.1 樣板代碼
4.2.2 插件
4.2.3 ns3命名空間
4.2.4 日誌記錄
4.2.5 主要功能
4.2.6 使用拓樸助手
4.2.7 使用應用程式
4.2.8 模擬器
4.2.9 建置腳本
4.3 ns-3 原始碼

第4章

概念概述

在開始學習或編寫 ns-3 程式碼之前,我們需要做的第一件事是解釋系統中的一些基本概念和抽象。其中大部分內容對某些人來說似乎是顯而易見的,但我們建議您花時間閱讀本節,以確保您有一個堅實的基礎。

4.1 關鍵抽象

在本節中,我們將了解一些網路上常用但在 ns-3 中具有特定含義的術語。

4.1.1 節點

在網際網路術語中,連接到網路的電腦設備稱為主機,有時也稱為終端系統。因為 ns-3 是一個網路模擬器而不是互聯網模擬器,所以我們故意不使用術語“主機”,因為它與互聯網及其協定密切相關。相反,我們使用一個更通用的術語,其他模擬器也使用它,它起源於圖論:節點(節點).

在 ns-3 中,計算設備的底層抽象稱為節點。這種抽像在 C++ 中由 Node 類別表示。班級 節點節點 (節點)提供了在模擬中操縱計算設備表示的方法。

你必須明白 節點 就像您添加功能的計算機一樣。您將添加應用程式、協定堆疊和外圍卡等內容以及允許電腦執行有用工作的驅動程式。我們在 ns-3 中使用相同的基本模型。

4.1.2 應用

一般來說,電腦軟體分為兩大類。系統軟體依照某種運算模型組織記憶體、處理器週期、磁碟、網路等各種電腦資源。系統軟體通常不會使用這些資源來執行對使用者直接有利的任務。使用者通常會執行應用程式來實現特定目標,該目標獲取並使用由系統軟體控制的資源。

通常,系統和應用程式軟體之間的界限是根據作業系統陷阱中發生的特權等級變更來劃分的。 ns-3 沒有作業系統的真正概念,因此沒有特權等級或系統呼叫的概念。不過,我們確實有一個應用程式的想法。正如「現實世界」中的軟體應用程式在電腦上運行來執行任務一樣,ns-3 應用程式在 ns-3 節點上運行來控制模擬世界中的模擬。

在 ns-3 中,產生某些建模活動的使用者程式的基本抽像是應用程式。這種抽像在 C++ 中由 Application 類別表示。 Application 類別提供了在模擬中操作使用者層級應用程式版本的視圖的方法。開發人員應該以物件導向程式設計的方式專門化 Application 類別來建立新的應用程式。在本教程中,我們將使用稱為 Application 類別的特化 UdpEcho客戶端應用程式 и UdpEcho伺服器應用程式。正如您所期望的,這些應用程式組成了一組用於生成和回顯網路封包的用戶端/伺服器應用程式。

4.1.3 頻道

在現實世界中,您可以將電腦連接到網路。在這些網路中傳輸資料的媒體通常稱為通道。當您將乙太網路線插入牆壁插座時,您的電腦就連接到了乙太網路連結。在模擬的 ns-3 世界中,節點連接到代表通訊通道的物件。這裡,通訊子網路的基本抽象稱為通道,在 C++ 中由 Channel 類別表示。

Channel頻道 提供管理子網路物件互動並將節點連接到它們的方法。開發人員還可以在物件導向的程式設計意義上對通道進行專門化。通道專業化可以對像電線這樣簡單的東西進行建模。專用通道還可以對複雜的事物進行建模,例如大型乙太網路交換器或無線網路中充滿障礙物的三維空間。

我們將在本教程中使用該通道的專用版本,稱為 Csma頻道Csma頻道, 點對點頻道點對點頻道 и Wifi頻道Wifi頻道. Csma頻道例如,對實作載波偵聽多路存取通訊環境的通訊子網路版本進行建模。這為我們提供了類似乙太網路的功能。

4.1.4 網路設備

過去,如果您想將電腦連接到網絡,則必須購買特定的網路電纜和需要安裝在電腦中的稱為(PC 術語)外圍卡的硬體設備。如果外圍卡實現了一些網路功能,則它們被稱為網路介面卡或網卡。如今,大多數電腦都配備了整合式網路介面硬件,用戶不再將其視為單獨的設備。

如果沒有控制其硬體的軟體驅動程序,網路卡將無法運作。在Unix(或Linux)中,一件週邊設備被歸類為設備。設備使用設備驅動程式進行管理,網路設備 (NIC) 使用網路設備驅動程式進行管理(網路裝置驅動程式)並統稱為網路設備(網路裝置)。在 Unix 和 Linux 中,您可以透過以下名稱來引用網路設備 eth0.

在 ns-3 中,網路設備抽象涵蓋軟體驅動程式和正在建模的硬體。在模擬中,網路設備被「安裝」在節點中,以允許其透過通道與其他節點進行通訊。就像真實的電腦一樣,一個節點可以透過多個裝置連接到多個通道 網路設備公司.

設備的網路抽像在 C++ 中由類別表示 網路裝置. 烏克蘭語 網路裝置 提供管理與 Node 和 Channel 物件的連接的方法;並且可以由開發人員在物件導向程式設計的意義上進行專門化。在本教程中,我們將使用 NetDevice 的幾個專用版本,稱為 Csma網路設備, 點對點網路設備 и WifiNet設備。就像乙太網路網路適配器被設計為與網路一起工作一樣 乙太網路 - ENET, Csma網路設備 設計用於與 Csma頻道, 點對點網路設備 設計用於與 點對點頻道WifiNet設備 - 設計用於與 Wifi頻道.

4.1.5 拓樸助手

在真實的網路中,您會發現新增(或內建)網路卡的主機。在 ns-3 中,我們會說您將看到連接了 NetDevices 的節點。在大型模擬網路中,您將需要組織許多物件之間的連接 節點, 網路裝置 и 渠道.

由於將 NetDevices 連接到節點、將 NetDevices 連接到連結、分配 IP 位址等。在 ns-3 中這是一項常見任務,為了使其盡可能簡單,我們提供了所謂的拓樸助手。例如,要建立一個NetDevice,需要執行許多ns-3核心操作,新增MAC位址,在Node中安裝網路設備,配置節點的協定棧,然後將NetDevice連接到Channel。將多個裝置連接到多點鏈路,然後將各個網路連接到 Internetworks 網路中,還需要做更多的工作。我們提供拓樸幫助器對象,將這些操作組合成一個易於使用的模型,以方便您使用。

4.2 第一個 ns-3 腳本

如果您按照上面的建議安裝了系統,您的主目錄中名為 repos 的目錄中將包含 ns-3 版本。到目錄 釋放

如果沒有這樣的目錄,則表示您在建置 ns-3 的發佈版本時沒有指定輸出目錄,建置如下:
$ ./waf configure —build-profile=release —out=build/release,
$ ./waf 構建

您應該會看到類似以下內容的目錄結構:

AUTHORS       examples      scratch       utils       waf.bat*
bindings      LICENSE       src           utils.py    waf-tools
build         ns3           test.py*      utils.pyc   wscript
CHANGES.html  README        testpy-output VERSION     wutils.py
doc           RELEASE_NOTES testpy.supp   waf*        wutils.pyc

到目錄 範例/教程。您應該會看到那裡有一個名為 第一抄送。這是一個腳本,它將在兩個節點之間建立一個簡單的點對點連接,並在節點之間傳輸一個資料包。讓我們逐行查看該腳本;為此,請在您最喜歡的編輯器中開啟first.cc。

4.2.1 樣板代碼
文件中的第一行是編輯器模式行 emacs的。它告訴 emacs 我們在原始程式碼中使用的格式約定(編碼風格)。

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */

這始終是一個頗具爭議的問題,因此我們需要澄清事實,並立即解決這個問題。與大多數大型專案一樣,ns-3 專案採用了所有貢獻的程式碼都必須遵循的程式設計風格。如果您想為專案貢獻代碼,您最終必須遵守 ns-3 編碼標準,如文件中所述 文件/codingstd.txt 或顯示在專案網頁上: https://www.nsnam.org/develop/contributing-code/coding-style/.

我們建議您習慣 ns-3 程式碼的外觀,並在使用我們的程式碼時套用此標準。整個開發團隊和貢獻者在一番抱怨後都同意了這一點。如果您使用 emacs 編輯器,上面的 emacs 模式行可以輕鬆正確地格式化。

ns-3 模擬器已獲得許可 GNU通用公共許可證。您將在每個 ns-3 分發文件中看到相應的 GNU 合法標頭。通常,您會在 GPL 文字和作者上方看到 ns-3 專案參與機構之一的版權聲明,如下所示。

/* 
* 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 "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"

為了幫助我們的高級腳本使用者應對系統中存在的大量頭文件,我們根據它們的用途將它們分組為大模組。我們提供一個頭文件,它將遞歸加載給定模組中使用的所有頭文件。我們使您能夠以很大的粒度下載一組文件,而不必精確搜尋您需要的標頭並可能獲得正確的依賴項清單。這不是最有效的方法,但它確實使編寫腳本變得更加容易。

每個 ns-3 包含檔案都放置在名為的目錄中 ns3 (build 子目錄)以避免建置過程中的檔案名稱衝突。文件 ns3/核心模組.h 對應於 ns-3 模組,您可以在目錄中找到它 原始碼/核心 在您安裝的版本中。在此目錄的清單中您會發現大量的頭檔。當你進行組裝時, 瓦夫 將公共頭檔放置在 ns3 目錄的子目錄中 建置/調試

如果沒有這樣的目錄,則表示您在建置 ns-3 的發佈版本時沒有指定輸出目錄,建置如下:
$ ./waf configure --build-profile=debug --out=build/debug
$ ./waf 構建

$ ./waf configure --build-profile=optimized --out=build/optimized
$ ./waf 構建

建置/優化,取決於您的配置。 瓦夫 也會自動產生一個模組包含檔案來載入所有公共頭檔。既然您當然虔誠地遵循本指南,那麼您已經完成了

$ ./waf -d debug --enable-examples --enable-tests configure

配置專案以運行包含範例和測試的調試版本。你也做了

$ ./waf

組裝項目。所以現在當你查看目錄時 ../../建置/調試/ns3,然後您將找到上面顯示的四個模組的頭檔等。可以查看這些文件的內容,發現其中包含了相應模組使用的所有公共文件。

4.2.3 ns3命名空間

腳本中的下一行 第一抄送 是一個命名空間聲明。

using namespace ns3;

ns-3 專案是在名為 ns3 的 C++ 命名空間中實現的。這會將所有 ns-3 相關的聲明分組到全域命名空間以外的範圍中,這有望有助於與其他程式碼的整合。使用 C++ 運算子將 ns-3 命名空間引入目前(全域)宣告區域。這是一種奇特的說法,在聲明之後,您無需在所有 ns-3 程式碼之前鍵入 ns3::scope 權限運算子即可使用它。如果您不熟悉命名空間,請參考幾乎所有 C++ 教科書並使用 std 命名空間和聲明來比較 ns3 命名空間 using namespace std; 在使用輸出運算子的範例中 COUT 和溪流。

4.2.4 日誌記錄

腳本的下一行是,

NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");

我們將使用此聲明作為討論我們的文件系統的方便場所 Doxygen的。如果您查看 ns-3 專案網站,您會在導覽列中找到文件連結。如果您單擊此鏈接,您將進入我們的文件頁面。有一個“最新版本”鏈接,可將您帶到 ns-3 最新穩定版本的文檔。如果您選擇“API 文件”鏈接,您將進入 ns-3 API 文件頁面。

在頁面左側,您將找到文件結構的圖形表示。 ns-3 導航樹中的模組 ns-3 「書」是一個不錯的起點。如果你透露 模塊,您將看到 ns-3 模組文件清單。如上所述,這裡模組的概念與上面模組中包含的檔案直接相關。 ns-3 日誌子系統在第 XNUMX 節討論 使用日誌記錄模組,所以我們將在本教程的後面部分再討論它,但是您可以透過查看模組來了解上述語句 核心然後打開書本 調試工具然後選擇頁面 記錄。點選 記錄.

您現在應該查看文檔 Doxygen的 對於模塊 記錄。在頁面頂部的巨集清單中,您將看到 NS_LOG_COMPONENT_DEFINE 的條目。在點擊連結之前,請務必查看註冊模組的“詳細說明”,以了解其整體工作原理。為此,您可以向下捲動或選擇圖表下方的“更多...”。

一旦您對發生的事情有了大致的了解,您就可以繼續查看特定 NS_LOG_COMPONENT_DEFINE 的文檔。我不會在這裡重複文檔,但總而言之,這一行聲明了一個名為的註冊組件 第一個腳本範例,它允許您透過引用名稱來啟用或停用控制台訊息記錄。

4.2.5 主要功能

在腳本的以下幾行中,您將看到,

int 
main (int argc, char *argv[])
{ 

這只是程式(腳本)主函數的聲明。與任何 C++ 程式一樣,您需要定義一個 main 函數,該函數首先被執行。這裡沒有什麼特別的。您的 ns-3 腳本只是一個 C++ 程式。以下行將時間解析度設為 1 奈秒,這是預設值:

Time::SetResolution (Time::NS);

時間分辨率,或簡稱分辨率,是可以使用的最小時間值(兩個時間之間的最小可表示差異)。您只能變更一次解析度。提供這種靈活性的機制會消耗內存,因此一旦明確設定了分辨率,我們就會釋放內存,從而防止進一步更新。 (如果沒有明確設定分辨率,則預設為一納秒,並且模擬開始時將釋放記憶體。)

以下兩行腳本用於啟用應用程式中內建的兩個日誌記錄元件 迴聲客戶端 и 迴聲伺服器:

LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO); LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);

如果您閱讀日誌記錄元件的文檔,您將看到可以在每個元件上啟用多個層級的日誌記錄/粒度。這兩行程式碼啟用 echo 用戶端和伺服器的偵錯日誌記錄到 INFO 等級。在此級別,應用程式將在模擬期間發送和接收資料包時列印訊息。

現在我們將開始建立拓撲並運行模擬。我們使用拓樸輔助物件來使這項工作盡可能簡單。

4.2.6 使用拓樸助手

我們腳本中的接下來兩行程式碼將實際建立代表模擬中的電腦的 Node ns-3 物件。

NodeContainer nodes;
nodes.Create (2);

在繼續之前,讓我們找到該類的文檔 節點容器。取得給定類別的文件的另一種方法是透過選項卡 課程 在頁面上 Doxygen的。如果您已經開啟了 Doxygen,只需向上捲動到頁面頂部並選擇「類別」標籤即可。您應該會看到一組新的選項卡,其中一個是類別列表。在此標籤下,您將看到所有 ns-3 類別的清單。向下捲動到 ns3::NodeContainer。當您找到一個類別時,請選擇它即可轉到該類別的文件。

正如我們所記得的,我們的關鍵抽象之一是節點。它代表我們要添加協議棧、應用程式和外圍卡等內容的電腦。拓樸助手 節點容器 提供了一種創建、管理和存取任何物件的便捷方法 節點,我們創建它來運行模擬。上面的第一行只是聲明 節點容器,我們稱之為節點。第二行呼叫節點物件的 Create 方法,並要求容器建立兩個節點。如中所述 Doxygen的,容器請求ns-3系統建立兩個對象 節點 並在內部儲存指向這些物件的指標。

腳本中建立的節點尚未執行任何操作。建立拓撲的下一步是將我們的節點連接到網路。我們支援的最簡單的網路形式是兩個節點之間的點對點連接。我們現在將創建這樣的連接。

點對點助手

我們使用熟悉的模式來建立點對點連接,使用拓樸輔助物件來完成連接所需的低階工作。回想一下我們的兩個關鍵抽象 網路裝置 и 渠道。在現實世界中,這些術語大致對應於外圍卡和網路電纜。通常,這兩件事彼此密切相關,沒有人可以指望共享,例如設備 乙太網路 - ENET 透過無線通道。我們的拓撲助手遵循這種密切關係,因此您將在此場景中使用單個對象 點對點助手 用於設定和連接 ns-3 對象 點對點網路設備 и 點對點頻道。腳本中的接下來三行:

PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); 
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

第一行,

PointToPointHelper pointToPoint;

在堆疊上建立物件的實例 點對點助手。從頂層的角度來看,以下行:

pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));

告訴對象 點對點助手 使用值“5 Mbit/s”(每秒五兆位元)作為“數據速率“。

從更具體的角度來看,字串「DataRate」對應的是我們所說的屬性 點對點網路設備。如果你看 Doxygen的 上課 ns3::點對點網路設備 以及該方法的文檔中 取得類型ID 您將找到為設備定義的屬性清單。其中包括屬性“數據速率」大多數使用者可見的 ns-3 物件都有類似的屬性清單。我們使用這種機制可以輕鬆設定模擬而無需重新編譯,正如您將在下一節中看到的那樣。

如同 ”數據速率在 PointToPointNetDevice 中,您將找到與 PointToPointChannel 相關的「Delay」屬性。最後一行

pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

говорит 點對點助手 使用值“2 ms”(兩毫秒)作為隨後創建的點對點鏈路的傳播延遲值。

網路設備容器

目前我們在腳本中 節點容器,其中包含兩個節點。我們有 點對點助手,為創建物件做準備 點對點網路設備 並使用 PointToPointChannel 物件連接它們。就像我們使用 NodeContainer 拓樸輔助物件來建立節點一樣,我們會問 點對點助手 為我們執行與設備的建立、配置和安裝相關的工作。我們需要所有已建立的物件的列表 網路裝置,所以我們使用 網路設備容器 以與我們使用相同的方式儲存它們 節點容器 來儲存我們創建的節點。接下來的兩行程式碼,

NetDeviceContainer devices;
devices = pointToPoint.Install (nodes);

完整的設備和通道設定。第一行聲明上面提到的設備容器,第二行完成主要工作。方法 安裝 目的 點對點助手 接受 節點容器 作為參數。裡面 網路設備容器 對於位於的每個節點 節點容器 已建立(對於點對點通信,必須恰好有兩個) 點對點網路設備 建立並保存在設備容器中。 點對點頻道 已建立並附加了兩個 點對點網路設備。創建物件後,屬性儲存在 點對點助手,用於初始化已建立的物件中對應的屬性。

撥打電話後 pointToPoint.Install(節點) 我們將有兩個節點,每個節點都安裝有一個點對點網路設備,並且它們之間有一條點對點鏈路。兩種設備都將配置為以每秒 XNUMX 兆位元的速度傳輸數據,通道上的傳輸延遲為 XNUMX 毫秒。

網路堆疊助手

我們現在已經配置了節點和設備,但是我們的節點沒有安裝協定棧。接下來的兩行程式碼將處理這個問題。

InternetStackHelper stack;
stack.Install (nodes);

網路堆疊助手 - 是互聯網堆疊的拓撲幫助程序,類似於點對點網路設備的 PointToPointHelper。方法 安裝 將 NodeContainer 作為參數。執行時,它將在每個容器節點上安裝互聯網堆疊(TCP、UDP、IP 等)。

IPv4地址助手

然後我們需要將我們的設備與 IP 位址關聯起來。我們提供拓樸助理來管理 IP 位址分配。使用者可見的唯一 API 是設定進行實際位址分配時要使用的基本 IP 位址和網路遮罩(這是在幫助程式中的較低層級完成的)。我們的範例腳本中的接下來兩行程式碼 第一抄送,

Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");

聲明位址幫助器物件並告訴它應該開始從網路 10.1.1.0 分配 IP 位址,使用 255.255.255.0 位元遮罩來確定。預設情況下,分配的位址將從 10.1.1.1 開始並單調增加,因此從此基址分配的第一個位址將為 10.1.1.2,然後是 3,依此類推。實際上,在低級別上,ns-XNUMX 系統會記住所有分配的IP 位址,如果您不小心創建了相同位址產生兩次的情況,則會產生致命錯誤(順便說一句,此錯誤很難調試)。

下面的程式碼行,

Ipv4InterfaceContainer interfaces = address.Assign (devices);

執行實際的地址分配。在 ns-3 中,我們使用該物件在 IP 位址和裝置之間建立連接 IPv4介面。正如我們有時需要助手創建的網路設備列表以供以後使用一樣,我們有時也需要物件列表 IPv4介面. IPv4介面容器 提供此功能。

我們建立了一個點對點網絡,安裝了堆疊並分配了 IP 位址。現在我們需要每個節點中的應用程式來產生流量。

4.2.7 使用應用程式

ns-3 系統的另一個主要抽像是 應用 (應用)。在這種情況下,我們使用兩個基類專業化 應用 ns-3 稱為 UdpEcho伺服器應用程式 и UdpEcho客戶端應用程式。與先前的情況一樣,我們使用輔助物件來配置和管理基礎物件。這裡我們使用 UdpEcho伺服器助手 и UdpEchoClient幫助r 的目標是讓我們的生活更輕鬆。

UdpEcho伺服器助手

First.cc 範例腳本中的以下程式碼行用於在我們先前建立的節點之一上配置 UDP 回顯伺服器應用程式。

UdpEchoServerHelper echoServer (9);

ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));

上面程式碼片段中的第一行程式碼創建 UdpEcho伺服器助手。像往常一樣,這本身並不是一個應用程序,它是一個幫助我們創建真實應用程式的物件。我們的約定之一是將所需的屬性傳遞給輔助物件的建構子。在這種情況下,幫助程式不能做任何有用的事情,除非給它伺服器偵聽資料包的連接埠號,客戶端也必須知道該連接埠號碼。在本例中,我們將連接埠號碼傳遞給輔助建構函數。反過來,構造函數只是簡單地執行以下操作: 設定屬性 與傳遞的值。稍後,如果需要,您可以使用 SetAttribute 為 Port 屬性設定不同的值。

與許多其他輔助對像一樣,該對象 UdpEcho伺服器助手 有一個方法 安裝。執行此方法可以有效地建立一個基本的回顯伺服器應用程式並將其綁定到主機。有趣的是,該方法 安裝 接受 節點容器 像其他參數一樣作為參數 安裝 我們已經看到的方法。

這裡的 C++ 隱式轉換採用此方法的結果 節點.Get(1) (它傳回一個指向節點物件的智慧型指標 - Ptr )並在匿名物件的建構函式中使用它 節點容器然後傳遞給該方法 安裝。如果無法在 C++ 程式碼中確定編譯和執行哪個方法簽名,請在隱式轉換中尋找。

現在我們看到了 迴聲伺服器安裝 即將安裝應用程式 UdpEcho伺服器應用程式 發現於 節點容器我們用它來管理我們的節點,索引為 1 的節點。方法 安裝 將返回一個容器,其中包含指向所有應用程式的指標(在本例中是一個,因為我們傳遞了一個匿名 節點容器,包含一個節點)由助手創建。

應用程式需要指定何時開始產生流量 “開始” 並且可能需要額外指定停止的時間 “停止”。我們提供這兩種選擇。這些時間是使用以下方法設定的 應用容器 開始 и 停止。這些方法接受類型的參數 Time。在本例中,我們使用明確的 C++ 轉換序列來取得 C++ 翻番 1.0 並將其轉換為 tns-3 Time 對象,該物件使用 Seconds 物件轉換為秒。請記住,轉換規則可以由模型作者控制,並且 C++ 有自己的規則,因此您不能總是指望參數按照您期望的方式轉換。兩條線

serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));

將導致回顯伺服器應用程式在模擬開始後一秒鐘啟動(自動開啟),並在模擬十秒後停止(關閉)。由於我們聲明了一個模擬事件(應用程式停止事件),該事件將在十秒內執行,因此至少會模擬十秒的網路操作。

UdpEchoClientHelper

客戶申請 錯過 以幾乎類似於伺服器的方式配置。有一個基礎對象 UdpEcho客戶端應用程式,這是受控的
UdpEchoClientHelper.

UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));

ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));;

但是,對於 echo 用戶端,我們需要設定五個不同的屬性。前兩個屬性在建立時設定 UdpEchoClientHelper。我們傳遞用於(在助手內部)設定屬性的參數 “遠端位址” и “遠端連接埠” 按照我們的約定將必要的參數傳遞給輔助建構函數。

讓我們記住我們使用過 IPv4介面容器 追蹤我們分配給設備的 IP 位址。 Interfaces 容器中的空介面將對應於 Nodes 容器中空節點的 IP 位址。介面容器中的第一個介面對應於節點容器中第一個節點的 IP 位址。因此,在第一行程式碼(上面)中,我們建立一個幫助程式並告訴它客戶端的遠端位址將是分配給伺服器所在主機的IP位址。我們還說我們需要安排將資料包發送到連接埠 XNUMX。

“MaxPackets”屬性告訴客戶端我們在模擬過程中可以發送的最大資料包數量。 「Interval」屬性告訴客戶端資料包之間等待的時間,「PacketSize」屬性告訴客戶端資料包的有效負載應該有多大。透過此屬性組合,我們告訴客戶端發送單個 1024 位元組資料包。

與echo伺服器一樣,我們設定echo客戶端的屬性 開始 и 停止,但這裡我們在伺服器開啟後一秒(模擬開始後兩秒)啟動客戶端。

4.2.8 模擬器

此時我們需要運行模擬。這是使用全域函數完成的 模擬器::運行.

Simulator::Run ();

當我們之前呼叫方法時,

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 秒處安排了兩個事件。通話結束後 模擬器::運行,系統將開始查看預定事件清單並執行它們。它將在 1,0 秒後首先觸發一個事件,這將觸發回顯伺服器應用程式(該事件又可以安排許多其他事件)。然後它將觸發一個安排在 t=2,0 秒的事件,該事件將啟動 echo 用戶端應用程式。同樣,本次活動可能也計劃舉辦更多活動。 echo 用戶端中的啟動事件實作將透過向伺服器發送資料包來開始模擬的資料傳輸階段。

向伺服器發送資料包的行為將觸發一系列事件,這些事件將在幕後自動安排,並根據我們在腳本中設定的計時參數實現發送回顯資料包的機制。

結果,由於我們只發送一個資料包(請記住,屬性 最大資料包數 設定為 XNUMX),由該單一客戶端 ping 發起的事件鏈將結束,並且模擬將進入待機模式。一旦發生這種情況,剩餘的預定事件將是事件 停止 對於伺服器和客戶端。當這些事件被執行時,將不再有任何事件可供進一步處理和 模擬器::運行 將返回控制權。模擬完成。

剩下的就是自己清理乾淨。這是透過呼叫全域函數來完成的 模擬器::摧毀。因為呼叫了輔助函數(或低階 ns-3 程式碼),這些函數的組織方式是將掛鉤插入模擬器中以銷毀建立的所有物件。您不需要自己追蹤任何這些物件 - 您所要做的就是調用 模擬器::摧毀 然後出去。 ns-3 系統將為您完成這項艱苦的工作。我們的第一個 ns-3 腳本 first.cc 的其餘幾行就是這樣做的:

Simulator::Destroy ();
return 0;
}

模擬器什麼時候停止?

ns-3 是離散事件 (DE) 模擬器。在這樣的模擬器中,每個事件都與其執行時間相關聯,隨著模擬的進行,模擬透過按照事件發生的順序處理事件來繼續。事件可以導致安排未來的事件(例如,計時器可以重新安排自身以在下一個時間間隔內完成計數)。

初始事件通常由實體發起,例如 IPv6 將調度網路上服務的發現、鄰居請求等。應用程式調度第一個資料包發送事件,依此類推。當處理一個事件時,它可以產生零個、一個或多個事件。隨著模擬的進行,事件會發生,要麼結束,要麼產生新的事件。如果事件隊列為空或偵測到特殊事件,模擬將自動停止 停止。事件 停止 由函數生成 模擬器::停止 (停止時間)。

在典型情況下,Simulator::Stop 絕對需要停止模擬:當存在自維持事件時。自我維持(或重複)的事件是指總是重新安排的事件。因此,他們總是保持事件隊列不為空。有許多協定和模組包含重複事件,例如:

• FlowMonitor - 定期檢查遺失的資料包;

• RIPng – 定期廣播路由表更新;

• ETC。

在這種情況下 模擬器::停止 正確停止模擬所必需的。另外,當ns-3處於模擬模式時,RealtimeSimulator用於將模擬時鐘與機器時鐘同步,並且 模擬器::停止 需要停止該過程。

課本上的許多仿真程式並沒有調用 模擬器::停止 顯式地,因為當排隊的事件耗盡時它們會自動終止。但是,這些程式也將接受 Simulator::Stop 呼叫。例如,第一個範例程式中的以下附加語句將安排在 11 秒時明確停止:

+ Simulator::Stop (Seconds (11.0));
  Simulator::Run ();
  Simulator::Destroy ();
  return 0;
}

上述內容實際上不會改變該程式的行為,因為該特定模擬會在 10 秒後自然結束。但是,如果您將上述語句中的停止時間從 11 秒更改為 1 秒,您會注意到模擬在任何輸出到達螢幕之前停止(因為輸出發生在大約 2 秒的模擬時間之後)。

在呼叫 Simulator::Run 之前呼叫 Simulator::Stop 很重要;否則 Simulator::Run 可能永遠不會將控制權傳回給主程式來執行停止!

4.2.9 建置腳本

我們讓創建簡單的腳本變得輕而易舉。您所要做的就是將腳本放在臨時目錄中,如果您運行,它將自動構建 瓦夫。咱們試試吧。返回頂層目錄並複製 範例/教程/first.cc 到目錄 劃傷

$ cd ../.. 
$ cp examples/tutorial/first.cc scratch/myfirst.cc

現在使用以下命令建立您的第一個範例腳本 WAF:

$ ./waf

您應該看到指示您的第一個範例已成功建立的訊息。

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)

現在您可以運行該範例(請注意,如果您在臨時目錄中建立程序,則必須從 劃傷):

$ ./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

在這裡您可以看到建置系統驗證檔案是否已建置然後執行它。您會看到 echo 用戶端上的元件項目表示它向 echo 伺服器 1024 發送了單一 10.1.1.2 位元組封包。您也可以看到 echo 伺服器上的日誌記錄元件顯示它從 1024 接收到了 10.1.1.1 位元組。回顯伺服器會默默地重播資料包,您可以在回顯客戶端的日誌中看到它從伺服器接收回資料包。

4.3 ns-3 原始碼

現在您已經使用了一些 ns-3 助手,您可以查看一些實現此功能的原始程式碼。最新的程式碼可以在我們的網站伺服器上透過以下連結查看: https://gitlab.com/nsnam/ns-3-dev.git。在那裡您將看到 ns-3 開發樹的 Mercurial 摘要頁面。在頁面頂部您會看到幾個鏈接,

summary | shortlog | changelog | graph | tags | files

繼續並選擇文件連結。這就是我們大多數儲存庫的頂層的樣子:

drwxr-xr-x                               [up]
drwxr-xr-x                               bindings python  files
drwxr-xr-x                               doc              files
drwxr-xr-x                               examples         files
drwxr-xr-x                               ns3              files
drwxr-xr-x                               scratch          files
drwxr-xr-x                               src              files
drwxr-xr-x                               utils            files
-rw-r--r-- 2009-07-01 12:47 +0200 560    .hgignore        file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 1886   .hgtags          file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 1276   AUTHORS          file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 30961  CHANGES.html     file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 17987  LICENSE          file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 3742   README           file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 16171  RELEASE_NOTES    file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 6      VERSION          file | revisions | annotate
-rwxr-xr-x 2009-07-01 12:47 +0200 88110  waf              file | revisions | annotate
-rwxr-xr-x 2009-07-01 12:47 +0200 28     waf.bat          file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 35395  wscript          file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 7673   wutils.py        file | revisions | annotate

我們的範例腳本位於目錄中 例子。如果您按一下範例,您將看到子目錄清單。子目錄中的檔案之一 教程-first.cc。如果您點擊 第一抄送 您將看到您剛剛學到的程式碼。

原始碼主要位於目錄 SRC。您可以透過點擊目錄名稱或點擊目錄名稱右側的檔案連結來查看原始程式碼。如果按一下 src 目錄,您將獲得 src 子目錄的清單。如果按一下 core 子目錄,您將找到檔案清單。您將看到的第一個文件(在撰寫本指南時)是 中止.h。如果您點擊連結 中止.h,您將被發送到來源文件 中止.h,其中包含用於在檢測到異常情況時退出腳本的有用巨集。我們在本章中使用的幫助程式的原始碼可以在目錄中找到 src/應用程式/幫助程序。請隨意瀏覽目錄樹以找出內容並了解 ns-3 程式的風格。

來源: www.habr.com

添加評論