蔡文郁, 劉曉玲
(杭州電子科技大學(xué) 電子信息學(xué)院,杭州 310018)
《計(jì)算機(jī)網(wǎng)絡(luò)系統(tǒng)》[1]是本科教學(xué)體系中的一個(gè)重要分支,其旨在讓學(xué)生掌握抽象的計(jì)算機(jī)網(wǎng)絡(luò)系統(tǒng)知識(shí)的同時(shí),并能通過(guò)自己的操作和改進(jìn)的協(xié)議進(jìn)行網(wǎng)絡(luò)性能仿真結(jié)果的分析,如果只靠黑板教學(xué)是難以達(dá)到這一教學(xué)目標(biāo)。網(wǎng)絡(luò)仿真[3]是通過(guò)計(jì)算機(jī)技術(shù)搭建網(wǎng)絡(luò)結(jié)構(gòu)和實(shí)現(xiàn)網(wǎng)絡(luò)協(xié)議的模擬網(wǎng)絡(luò)行為,是一項(xiàng)重要的計(jì)算機(jī)網(wǎng)絡(luò)仿真技術(shù)。相比于搭建一個(gè)實(shí)驗(yàn)室測(cè)試網(wǎng)絡(luò)平臺(tái),網(wǎng)絡(luò)仿真技術(shù)可以使用相對(duì)較少的時(shí)間和較低的費(fèi)用基本實(shí)現(xiàn)所需要研究的網(wǎng)絡(luò)模型,作為《計(jì)算機(jī)網(wǎng)絡(luò)系統(tǒng)》課程中一種重要的輔助實(shí)驗(yàn)手段。NS-3[4]作為一種開(kāi)源、免費(fèi)的網(wǎng)絡(luò)仿真軟件,可以實(shí)現(xiàn)對(duì)大部分網(wǎng)絡(luò)協(xié)議的仿真,其具有開(kāi)源性,學(xué)生可以在其提供的已有的模塊下進(jìn)行改進(jìn),大大提升學(xué)生的學(xué)習(xí)興趣。本文將這種開(kāi)源的網(wǎng)絡(luò)仿真軟件NS-3應(yīng)用在計(jì)算機(jī)網(wǎng)絡(luò)課程的教學(xué)過(guò)程中,通過(guò)設(shè)計(jì)一些啟發(fā)式實(shí)驗(yàn)案例,讓學(xué)生了解NS-3仿真軟件,讓學(xué)生對(duì)網(wǎng)絡(luò)通信協(xié)議有直觀深入的理解,進(jìn)而提高教學(xué)效果。
網(wǎng)絡(luò)仿真(Network Simulator-3,NS-3)是一種旨在學(xué)術(shù)研究和教學(xué)需要的離散事件模擬器,其在可擴(kuò)展性、移植性、開(kāi)源性和完整性等方面的特征都優(yōu)于現(xiàn)有的大多數(shù)網(wǎng)絡(luò)模擬器。NS-3可以構(gòu)建各種網(wǎng)絡(luò)結(jié)構(gòu),可以仿真模擬各種協(xié)議并對(duì)其進(jìn)行比較和改進(jìn)。NS-3中的模塊支持兩種語(yǔ)言編寫(xiě),分別是C++和Python。NS-3的仿真結(jié)果有靜態(tài)和動(dòng)態(tài)兩種形式,其中靜態(tài)結(jié)果有文本文件和圖表方式,動(dòng)態(tài)圖包括離線動(dòng)畫(huà)演示工具NetAnim和在線可視化模塊PyViz。NS-3組織結(jié)構(gòu)[5]和模型間的依賴關(guān)系如圖1所示,依次為核心模塊(Core)、網(wǎng)絡(luò)模塊(Network)、互聯(lián)網(wǎng)模塊(Internet)、移動(dòng)模塊(Mobility)、應(yīng)用模塊(Applications)和Helper類。每個(gè)模塊都有自己的類和實(shí)現(xiàn)方法,各個(gè)模塊相互獨(dú)立和實(shí)現(xiàn)功能。NS-3這種分層次的模塊組織結(jié)構(gòu),類似于TCP/IP協(xié)議,使各層各負(fù)其責(zé),在物理上、邏輯上相互獨(dú)立,便于研究者設(shè)計(jì)自己的網(wǎng)絡(luò)模型。
圖1 NS-3組織結(jié)構(gòu)
NS-3網(wǎng)絡(luò)仿真平臺(tái)搭建包括8個(gè)步驟,如圖2所示。
圖2 NS-3仿真平臺(tái)搭建流程圖
此案例的網(wǎng)絡(luò)結(jié)構(gòu)如圖3所示,多個(gè)無(wú)線客戶端節(jié)點(diǎn)需要訪問(wèn)PC服務(wù)器節(jié)點(diǎn),其中無(wú)線客戶端節(jié)點(diǎn)首先與無(wú)線AP節(jié)點(diǎn)連接,無(wú)線AP節(jié)點(diǎn)通過(guò)以太網(wǎng)連接PC服務(wù)器。該案例通過(guò)NS-3仿真演示實(shí)現(xiàn)有線網(wǎng)絡(luò)和無(wú)線網(wǎng)絡(luò)的混合通信,仿真過(guò)程的動(dòng)畫(huà)演示使用PyViz輔助工具,讓學(xué)生掌握無(wú)線WiFi通信技術(shù)以及異型網(wǎng)絡(luò)的綜合使用能力。
圖3 網(wǎng)絡(luò)仿真場(chǎng)景
2.1.1仿真場(chǎng)景
仿真網(wǎng)絡(luò)結(jié)構(gòu)如圖4所示,n5、n6是WiFi移動(dòng)節(jié)點(diǎn),n0是無(wú)線訪問(wèn)節(jié)點(diǎn)(Access Point,AP),n1~n4是有線局域網(wǎng),n0和n1是點(diǎn)到點(diǎn)的通信鏈路[10]。
圖4 網(wǎng)絡(luò)仿真場(chǎng)景
2.1.2仿真腳本的關(guān)鍵代碼
//“include”函數(shù)來(lái)引入NS-3中已編譯模塊,如:點(diǎn)到點(diǎn)模塊(point-to-point)、移動(dòng)模塊(mobility)等。
#include "ns3/point-to-point-module.h"
#include "ns3/mobility-module.h"
//此代碼中使用了NS-3提供的日志模塊功能,可根據(jù)Logging給出的信息點(diǎn)網(wǎng)絡(luò)環(huán)境進(jìn)行程序調(diào)試。
NS_LOG_COMPONENT_DEFINE ("ThirdScriptExample");
//通過(guò)調(diào)用CommandLine命令為程序引入命令行模式,用戶通過(guò)命令行模式去設(shè)定參數(shù)來(lái)改變程序中參數(shù)值,
CommandLine cmd; cmd.Parse (argc,argv);
//創(chuàng)建2個(gè)節(jié)點(diǎn)用于連接點(diǎn)到點(diǎn)鏈路
NodeContainer p2pNodes; p2pNodes.Create (2);
//構(gòu)建點(diǎn)對(duì)點(diǎn)連接,通過(guò)PointToPointHelper類設(shè)置網(wǎng)絡(luò)節(jié)點(diǎn)的點(diǎn)到點(diǎn)鏈路的網(wǎng)絡(luò)設(shè)備和信道屬性
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
//借用Install方法將設(shè)備安裝到節(jié)點(diǎn)中
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install (p2pNodes);
//創(chuàng)建3個(gè)以太網(wǎng)網(wǎng)絡(luò)節(jié)點(diǎn),并將點(diǎn)到點(diǎn)節(jié)點(diǎn)容器中的第一個(gè)節(jié)點(diǎn)加入到CSMA設(shè)備的節(jié)點(diǎn)容器
NodeContainer csmaNodes; csmaNodes.Add (p2pNodes.Get (1)); csmaNodes.Create (3);
//通過(guò)CsmaHelper類設(shè)置網(wǎng)絡(luò)節(jié)點(diǎn)的以太網(wǎng)的網(wǎng)絡(luò)設(shè)備和信道屬性,并用Install方法將設(shè)備安裝到節(jié)點(diǎn)中
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", StringValue
("100Mbps"));
csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
NetDeviceContainer csmaDevices; csmaDevices = csma.Install (csmaNodes);
//創(chuàng)建2個(gè)WiFi網(wǎng)絡(luò)節(jié)點(diǎn),再將剩余的一個(gè)點(diǎn)到點(diǎn)鏈路節(jié)點(diǎn)作為接入點(diǎn)AP
NodeContainer WiFiStaNodes; WiFiStaNodes.Create (2); NodeContainer WiFiApNode = p2pNodes.Get (0);
//通過(guò)配置PHY和通道助手來(lái)構(gòu)建無(wú)線設(shè)備和無(wú)線節(jié)點(diǎn)之間的互連通道
YansWiFiChannelHelper channel = YansWiFiChannelHelper::Default ();
YansWiFiPhyHelper phy = YansWiFiPhyHelper::Default ();
WiFiHelper WiFi;
WiFi.SetRemoteStationManager ("ns3::AarfWiFiManager");
WiFiMacHelper mac;
staDevices = WiFi.Install (phy, mac, WiFiStaNodes);
//配置AP節(jié)點(diǎn)
mac.SetType ("ns3::ApWiFiMac", "Ssid", SsidValue (ssid));
NetDeviceContainer apDevices;
apDevices = WiFi.Install (phy, mac, WiFiApNode);
//使用MobilityHelper類設(shè)置WiFi節(jié)點(diǎn)的初始位置和移動(dòng)模型
MobilityHelper mobility;
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
"MinX", DoubleValue (-50.0), "MinY", DoubleValue (50.0),
"DeltaX", DoubleValue (5.0),"DeltaY", DoubleValue (-50.0),
"GridWidth", UintegerValue (1),"LayoutType", StringValue ("RowFirst"));
//WiFi節(jié)點(diǎn)的移動(dòng)模型是隨機(jī)游走模型:RandomWalk2dMobilityModel
mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
"Bounds", RectangleValue (Rectangle (-150, 150, -150, 150)));
//通過(guò)InternetStackHelper類安裝協(xié)議棧
InternetStackHelper stack; stack.Install (csmaNodes);stack.Install (WiFiApNode); stack.Install (WiFiStaNodes);
//配置IP地址,點(diǎn)到點(diǎn)鏈路節(jié)點(diǎn)在網(wǎng)段10.1.1.0/24,CSMA節(jié)點(diǎn)在網(wǎng)段10.1.2.0/24,WiFi節(jié)點(diǎn)在網(wǎng)段10.1.3.0/24
Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0"); p2pInterfaces = address.Assign (p2pDevices);
address.SetBase ("10.1.2.0", "255.255.255.0"); csmaInterfaces = address.Assign (csmaDevices);
address.SetBase ("10.1.3.0", "255.255.255.0"); address.Assign (staDevices);address.Assign (apDevices);
//設(shè)置以太網(wǎng)節(jié)點(diǎn)3為echo服務(wù)端程序,同時(shí)設(shè)置服務(wù)器啟動(dòng)時(shí)間。
UdpEchoServerHelper echoServer (9);
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (3));
serverApps.Start (Seconds (1.0));
//設(shè)置WiFi網(wǎng)絡(luò)中的一個(gè)節(jié)點(diǎn)為客戶端,并配置相關(guān)屬性
UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (100));
ApplicationContainer clientApps = echoClient.Install (WiFiStaNodes.Get (nWiFi - 1));
//啟用互聯(lián)網(wǎng)絡(luò)路由作用與建立好的互連網(wǎng)絡(luò)
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
//運(yùn)行模擬、清空、退出程序
Simulator::Run (); Simulator::Destroy (); return 0;
2.1.3仿真實(shí)驗(yàn)及結(jié)果分析
仿真結(jié)果分析:根據(jù)圖5(a)和(b)可以直觀生動(dòng)的看出節(jié)點(diǎn)之間的數(shù)據(jù)流動(dòng)。從圖6可以看出,在終端中輸入編譯代碼并執(zhí)行腳本,從輸出的日志信息可以看出模擬通信場(chǎng)景運(yùn)行到2 s時(shí)客戶端發(fā)送1 024 Byte給地址為10.1.2.4的服務(wù)器,客戶端和服務(wù)器處于不同的網(wǎng)段。之后服務(wù)器收到來(lái)自10.1.3.2客戶端的數(shù)據(jù)分組,同時(shí)發(fā)送相同字節(jié)給客戶端,而且客戶端成功接收??梢钥吹椒抡娼Y(jié)果與程序中設(shè)定的發(fā)送數(shù)據(jù)包的時(shí)間點(diǎn)和數(shù)據(jù)包發(fā)送的發(fā)送端和接收端完全一致。
(a) 初始仿真場(chǎng)景
(b) 混合通信場(chǎng)景
圖5 混合通信仿真場(chǎng)景
圖6 編譯結(jié)果
如圖7所示,節(jié)點(diǎn)之間采用點(diǎn)到點(diǎn)通信,且節(jié)點(diǎn)均處于靜止?fàn)顟B(tài),采用添加中繼節(jié)點(diǎn)的方式實(shí)現(xiàn)節(jié)點(diǎn)的數(shù)據(jù)連通。此案例主要用于演示點(diǎn)到點(diǎn)中繼通信的原理,提高學(xué)生中繼通信的感官認(rèn)識(shí),從而激發(fā)學(xué)生學(xué)習(xí)并掌握短距離無(wú)線組網(wǎng)技術(shù)的興趣。
圖7 網(wǎng)絡(luò)仿真場(chǎng)景
2.2.1仿真場(chǎng)景
本仿真場(chǎng)景中一共設(shè)置了10個(gè)節(jié)點(diǎn),如圖8所示,其中n2~n11均位于不同的網(wǎng)段,n0和n1屬于中繼節(jié)點(diǎn),并且設(shè)置節(jié)點(diǎn)n4和節(jié)點(diǎn)n9進(jìn)行通信。
圖8 網(wǎng)絡(luò)仿真場(chǎng)景
2.2.2仿真腳本的關(guān)鍵代碼
#include "ns3/netanim-module.h"
//構(gòu)建網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu),如:設(shè)置節(jié)點(diǎn)0分別與節(jié)點(diǎn)1、2、3、4、5和6連接
pAnim->UpdateLinkDescription (0, 1, oss.str ());
pAnim->UpdateLinkDescription (0, 2, oss.str ());
pAnim->UpdateLinkDescription (0, 3, oss.str ());
pAnim->UpdateLinkDescription (0, 4, oss.str ());
pAnim->UpdateLinkDescription (0, 5, oss.str ());
pAnim->UpdateLinkDescription (0, 6, oss.str ());
// 設(shè)置 IP地址
d.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.1.0", "255.255.255.0"),
Ipv4AddressHelper ("10.2.1.0", "255.255.255.0"),
Ipv4AddressHelper ("10.3.1.0", "255.255.255.0"));
// 生成XML文件
std::string animFile = "dynamic_linknode.xml" ;
pAnim = new AnimationInterface (animFile);
2.2.3仿真實(shí)驗(yàn)及結(jié)果分析
仿真結(jié)果采用兩種可視化界面PyViz和NetAnim方式觀測(cè),如圖9所示。仿真結(jié)束后使用NetAnim讀取程序執(zhí)行過(guò)程中生成的XML文件,可離線演示網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)和節(jié)點(diǎn)間數(shù)據(jù)分組流動(dòng)等動(dòng)畫(huà)過(guò)程。
此仿真的場(chǎng)景是多跳無(wú)線網(wǎng)絡(luò)Ad Hoc[11],如圖10所示,其結(jié)構(gòu)采用一種省略無(wú)線中介設(shè)備AP而搭建起來(lái)的對(duì)等網(wǎng)絡(luò)結(jié)構(gòu),只需要安裝無(wú)線網(wǎng)卡,就可以實(shí)現(xiàn)計(jì)算機(jī)之間的通信。對(duì)于多跳無(wú)線自組網(wǎng)絡(luò)來(lái)說(shuō),路由協(xié)議是非常重要的。其中主動(dòng)路由協(xié)議和按需路由協(xié)議較為典型,因此仿真了DSR和DSDV兩種路由協(xié)議的建立路徑的過(guò)程和結(jié)果分析。此案例主要用于演示無(wú)線多跳網(wǎng)絡(luò)的工作原理以及不同路由協(xié)議的性能比較,提升學(xué)生參與網(wǎng)絡(luò)傳輸核心路由協(xié)議設(shè)計(jì)的學(xué)習(xí)熱情。
2.3.1仿真場(chǎng)景
本案例是基于Ad-Hoc網(wǎng)絡(luò)[12-14],設(shè)置了20個(gè)可隨機(jī)移動(dòng)的節(jié)點(diǎn),其中節(jié)點(diǎn)2(Node2)為數(shù)據(jù)發(fā)送端,節(jié)點(diǎn)0(Node0)為數(shù)據(jù)接收端。
(a) 點(diǎn)到點(diǎn)通信可視化界面
(b) 仿真拓?fù)浣Y(jié)構(gòu)圖
(c) 數(shù)據(jù)分組統(tǒng)計(jì)
(d) 節(jié)點(diǎn)9發(fā)送數(shù)據(jù)
(e) 途徑節(jié)點(diǎn)1和節(jié)點(diǎn)0
(f) 節(jié)點(diǎn)4發(fā)送數(shù)據(jù)
圖9 無(wú)線中繼通信演示
圖10 網(wǎng)絡(luò)仿真場(chǎng)景
2.3.2仿真腳本的關(guān)鍵代碼
//設(shè)置節(jié)點(diǎn)的移動(dòng)模型為隨機(jī)路徑
adhocMobility.SetMobilityModel ("ns3::RandomWaypoint MobilityModel",
"Speed", StringValue (speedUniformRandomVariable Stream.str ()),
"Pause", StringValue (pauseConstantRandomVariable Stream.str ()),
"PositionAllocator", PointerValue (taPositionAlloc));
adhocMobility.Install (adhocNodes);
//通過(guò)DsdvHelper類引入DSDV路由協(xié)議,同理也可以引入DSR路由協(xié)議。
DsdvHelper dsdv; InternetStackHelper stack; stack.SetRoutingHelper (dsdv);
//設(shè)置節(jié)點(diǎn)0為數(shù)據(jù)接收端,節(jié)點(diǎn)2為數(shù)據(jù)發(fā)送端,且設(shè)置節(jié)點(diǎn)2在20 s時(shí)開(kāi)始發(fā)送數(shù)據(jù)
ApplicationContainer apps_sink = sink.Install (adhocNodes.Get (0));
apps_sink.Start (Seconds (20.0));
OnOffHelper onoff1 ("ns3::UdpSocketFactory", Address (InetSocketAddress (allInterfaces.GetAddress (0), port)));
onoff1.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"));
onoff1.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0.0]"));
ApplicationContainer apps1 = onoff1.Install
(adhocNodes.Get (2));
2.3.3仿真實(shí)驗(yàn)及結(jié)果分析
仿真結(jié)果如圖11所示。
(a) DSDV協(xié)議Node2節(jié)點(diǎn)泛洪廣播
(b) DSDV協(xié)議Node2找到的第1條路徑
(c) DSDV協(xié)議Node2找到的第2條路徑
(d) DSR協(xié)議泛洪廣播
(e) DSR協(xié)議Node2找到的第1條路徑
(f) DSR協(xié)議Node2找到的第2條路徑
從可視化動(dòng)態(tài)仿真過(guò)程圖中,可以直觀地看出在同一種動(dòng)態(tài)變化的網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)的仿真場(chǎng)景。DSR協(xié)議比DSDV協(xié)議尋找到兩節(jié)點(diǎn)通信路徑所花費(fèi)的時(shí)間要少,這是因?yàn)樵趧?dòng)態(tài)變化的網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)下,由于鄰居信息表需要實(shí)時(shí)更新,主動(dòng)路由協(xié)議額外負(fù)荷較高。
本文將NS-3網(wǎng)絡(luò)仿真平臺(tái)引入到《計(jì)算機(jī)網(wǎng)絡(luò)系統(tǒng)》課程的教學(xué)中,通過(guò)在NS-3中構(gòu)建設(shè)計(jì)的3種不同網(wǎng)絡(luò)通信協(xié)議啟發(fā)式案例,運(yùn)用NS-3中多樣化的仿真方式,如Logging、動(dòng)畫(huà)演示工具(NetAnim)和可視化模塊(PyViz)等,將網(wǎng)絡(luò)課程中抽象的理論知識(shí)形象直觀地呈現(xiàn)在學(xué)生面前,使學(xué)生對(duì)網(wǎng)絡(luò)知識(shí)點(diǎn)有了較為直觀的了解,進(jìn)而激發(fā)學(xué)生探索網(wǎng)絡(luò)知識(shí)的欲望,起到事半功倍的效果。當(dāng)學(xué)生熟練掌握NS-3的模塊內(nèi)容和執(zhí)行方式后,還可以繼續(xù)引導(dǎo)學(xué)生向更深層次的計(jì)算機(jī)網(wǎng)絡(luò)協(xié)議的核心實(shí)現(xiàn)與編程技術(shù),為后續(xù)課程的學(xué)習(xí)奠定了一定基礎(chǔ)。