简单的多对一传输ns2仿真

实验名称:简单的多对一传输仿真

实验目的:
1。研究怎么实现多对一传输。

实验步骤:

1。写c++代码并注册报文头。

先说一下多对一传输的方式。最开始,接收端发送控制报文给所有的发送端,告诉他们要发送多少报文。

发送端按要求的数量发送完报文后,给接收端一个ack信息。

接收端收到所有发送端的ack报文后,则重新发送控制报文给所有的发送端。这样周而复始。

接收端为了和多个发送端通信,需要有多个agent,而每个app只能连接到一个agent上。如此,接收端上就有多个app,那么这多个app怎么通信呢?怎么知道彼此的状态?直觉上,接收端应该只有一个app在运行,多个app也让我们心理上不爽。这里我想到一个小技巧,也是在开发p2p点播时受到的提示。那就是,每个结点上除了一个总控的app,还要维持很多connection。connection负责和别的结点的连接。这些connection其实也是特殊的app,控制底层进行数据传输的agent。它们同时又向总控的app报告自己的情况,由总控的app对他们进行调度。说到这,你可能已经明白了,在这次仿真中,我要用两层app,顶层是一个总控的app,下层的app控制它们连接的agent。
为此,我定义了两个继承自application的类:SimpleApp和SimpleConnection。SimpleConnection就是底层控制agent的类,定义如下:

class SimpleConnection : public Application
{
public:
SimpleConnection();

//从agent接收报文,并进行处理。如果是控制报文,则按要求的数量发送报文。
//如果是ack报文,则向顶层的app报告。
//这个接口原来是Application没有的,为此要修改app.h,加上这个接口。
virtual void recv_msg(int nbytes, const char *msg = 0)end_ctrl(); R/> //发送控制报文,参数表示要求对方发送的报文数。
void send_ctrl(int);

//发送数据报文,每发送一个,需要发送的报文数减1,减到0时,向对方发送ack信息。
void send_data_pkt( );
//是否已经完成发送报文的任务
inline int done();

//设置指向上层app的指针
inline void App( SimpleApp *);
protected:
double next_send_time(); //计算发送下一个数据报文的时间
void send_ack(); //向对方发送ack信息
SimpleApp * app_; //指向上层app的指针
int done_; //是否已经完成任务
int tosend_; //要发送的报文数
SendTimer timer_; //一个计时器,用于发送报文的调度
int pktsize_; //数据报文的大小
double rate_; //连接速度,即每秒多少bit
};

SimpleApp是上层进行调度的类,是真正的应用,定义如下:

//=====================================================
// app: control multi connections
//=====================================================
class SimpleApp : public Application
{
public:
SimpleApp();

//检查是否所有的发送端都已经完成了任务,
//如果是,向他们发送新的控制报文。
void is_all_done();

protected:
void start(); //开始运转,置running_为真,并向所有的发送端发送控制报文
void stop(); //置running_为false

//把一个新的connection加入连接链表中
void add_connection(SimpleConnection *);

void send_ctrl(); //向所有发送端发送控制报文

//定义在tcl中能够调用的命令,这里实现了add-connection命令
virtual int command(int argc, const char*const* argv);
private:
vector cons_; //存放所有connection指针的链表
bool running_; //运行状态
};

  

另外,为了方便对agent进行控制,我们也定义了自己的agent。主要是重新实现了sendmsg和recv两个函数,方便我们对报文进行处理。
最初,我也想用原来的UdpAgent。却发现它的sendmsg和recv都是对报文中的AppData进行处理,让我没办法处理自己定义的消息头。
通过读ns-process.h中AppData的定义代码,发现AppData只有一个数据成员,就是数据类型,不可能含有报文头等信息。而实际上,报文头信息在Packet的数据成员bits_中。
“一怒之下”,我重写了自己的agent。

下面是我自己定义的报文头的定义:

//=============================================
// new packet header
//=============================================
struct hdr_simple
{
int type; //0-normal,1-ctrl,2-ack
int pkt_num; //the number of packets to send

static int offset_;
inline static int& offset() { return offset_; }
inline static hdr_simple* access(const Packet* p) {
return (hdr_simple*) p->access(offset_);
}
};

定义了自己的报文头,别忘了在packet.h和ns-packet.tcl中注册一下自己的报文头,当然,也不要忘了在.cc文件中定义一个linkage。具体怎么做,请参考《ns by example》吧,那讲的很详细。

2。重新编译ns。
上面的工作做完后,把代码文件放在一个目录中,然后改一下makefile。例如:我所有类的定义和实现都写在simple.h和simple.cc中,并且我把它们放在了apps目录下,我这样改makefile:

...
common/ivs.o common/messpass.o common/tp.o common/tpm.o apps/worm.o apps/simple.o tcp/tcp.o tcp/tcp-sink.o tcp/tcp-reno.o ...

只有红色的部分是我加的,很简单吧。保存makefile,重新编译吧,如果没报错,就是编译成功了。

3。写tcl脚本。
其实,我不是在扩充完ns2之后才写的tcl脚本,而是之前写的。这样,我在写脚本的时候,我就知道我需要哪些功能,需要定义哪些tcl能够调用的命令了,相当于是个分析用户需求的部分。我的tcl代码如下:

 1 # by jiqing 2007-6-6
 2 set ns [new Simulator]
 3 #color
 4 $ns color 1 Blue
 5 $ns color 2 Red
 6 $ns color 3 Green
 7
 8 #open a nam trace file
 9 set nf [open out.nam w]
10 $ns namtrace-all $nf
11
12 #open a trace file
13 set tf [open out.tr w]
14 $ns trace-all $tf
15
16 #finish procedure
17
18 proc finish {} {
19 global ns nf tf
20 $ns flush-trace
21 close $nf
22 close $tf
23 exec ./nam out.nam & exit 0
24 }
25
26 #create nodes
27 set node_(s1) [$ns node]
28 set node_(s2) [$ns node]
29 set node_(s3) [$ns node]
30 set node_(r) [$ns node]
31
32 #create links
33 $ns duplex-link $node_(s1) $node_(r) 1Mb 10ms DropTail
34 $ns duplex-link $node_(s2) $node_(r) 1.5Mb 10ms DropTail
35 $ns duplex-link $node_(s3) $node_(r) 1Mb 10ms DropTail
36
37 #relayout
38 $ns duplex-link-op $node_(s1) $node_(r) orient right-down
39 $ns duplex-link-op $node_(s2) $node_(r) orient right
40 $ns duplex-link-op $node_(s3) $node_(r) orient right-up
41
42 #add udp agents
43 set udp_(s1) [new Agent/JiqingUDP]
44 $ns attach-agent $node_(s1) $udp_(s1)
45 set udp_(r1) [new Agent/JiqingUDP]
46 $ns attach-agent $node_(r) $udp_(r1)
47 $ns connect $udp_(s1) $udp_(r1) $udp_(s1) set fid_ 1 $udp_(r1) set fid_ 1
48 set udp_(s2) [new Agent/JiqingUDP]
49 $ns attach-agent $node_(s2) $udp_(s2) set udp_(r2) [new Agent/JiqingUDP] $ns attach-agent $node_(r) $udp_(r2) $ns connect $udp_(s2) $udp_(r2) $udp_(s2) set fid_ 2 $udp_(r2) set fid_ 2 set udp_(s3) [new Agent/JiqingUDP] $ns attach-agent $node_(s3) $udp_(s3) set udp_(r3) [new Agent/JiqingUDP] $ns attach-agent $node_(r) $udp_(r3) $ns connect $udp_(s3) $udp_(r3) $udp_(s3) set fid_ 3 $udp_(r3) set fid_ 3 #add simpleconnections set app_(s1) [new Application/SimpleCon] $app_(s1) attach-agent $udp_(s1) set app_(s2) [new Application/SimpleCon] $app_(s2) attach-agent $udp_(s2) set app_(s3) [new Application/SimpleCon] $app_(s3) attach-agent $udp_(s3) set app_(r1) [new Application/SimpleCon] $app_(r1) attach-agent $udp_(r1) set app_(r2) [new Application/SimpleCon] $app_(r2) attach-agent $udp_(r2) set app_(r3) [new Application/SimpleCon] $app_(r3) attach-agent $udp_(r3) set app_(global1) [new SIMPLE_APP] $app_(global1) add-connection $app_(s1) set app_(global2) [new SIMPLE_APP] $app_(global2) add-connection $app_(s2) set app_(global3) [new SIMPLE_APP] $app_(global3) add-connection $app_(s3) set app_(global4) [new SIMPLE_APP] $app_(global4) add-connection $app_(r1) $app_(global4) add-connection $app_(r2) $app_(global4) add-connection $app_(r3) 

#schedule... $ns at 0.1 "$app_(global4) start" $ns at 4.0 "$app_(global4) stop" $ns at 4.5 "finish" $ns run

这个脚本定义了三个发送端,一个接收端,每个peer上都运行了一个SimpleApp,而每个agent上都连接有一个SimpleConnection,然后通过add-connection把app和connection连接起来。

4。仿真。
这一步没什么说的,./ns XXX.tcl就行了。

5。用awk处理数据。
这就看你想算什么了。我很无聊,只是想算每个时间各个发送端发送的报文数。

 BEGIN{
 sended1 = 0;
 sended2 = 0;
 sended3 = 0;
 i = 0;
}

{
 action = $1;
 time = $2;
 sender = $3;

 #you may use digital or character
 if(action=="r" &&( sender==0 ||sender==1 || sender==2) )
 {
  if(sender == 0)
   sended1++;
  else if( sender == 1)
   sended2++;
  else
   sended3++;

  #don‘t begin with digital
  _1send[i] = sended1;
  _2send[i] = sended2;
  _3send[i] = sended3;
  time_point[i] = time;

  i++;
 }
}

END{
 printf("%.2f\t%.2f\t%.2f\t%.2f\n",0,0,0,0);
 for(j=0;j
  printf("%.2f\t%.2f\t%.2f\t%.2f\n",time_point[j],_1send[j],_2send[j],_3send[j]);
 }
}

写好代码,保存为measure_pkts.awk。
在命令行下执行:
awk -f measure_pkts.awk > results.txt
就会把分析的结果写入results.txt。

6。用gnuplot画图。
最后,就是看见结果的时候了。进入gnuplot:
plot "results.txt" using 2, "results.txt" using 3, "results.txt" using 4
就可以看见结果了。

实验结果:

没什么好讲的了,目的已经达到。

参考文献:
1。Jae Chung,Mark Claypool. Ns by Example.
2。柯志亨博士的"增加和修改模块.htm"。
3。bittorrent仿真的源码。
4。ns2的源代码。

时间: 2024-10-08 01:17:01

简单的多对一传输ns2仿真的相关文章

NS2仿真过程中nam动画的保存

关于NS2仿真过程中nam动画的保存为gif格式大家可以参考科学网的这篇博客,http://blog.sciencenet.cn/blog-281551-390046.html,通过实验,个人觉得其实现过程比较复杂. 当然nam程序除了linux版本以外,还有windows版本.可到如下网站进行下载.http://www.isi.edu/nsnam/nam/ ,然后即可利用该可执行文件打开仿真时保存的.nam文件.如在"运行"中键入D:\nam-1.0a11a-win32.exe D:

NS2仿真时报错“can't read "node_(5)": no such element in array”

在用NS2进行无线网络仿真时,通过生成cbr数据流,生成场景文件,导入运行tcl时,有可能出现下面错误: 在运行10个节点以上是没有错误,5个或者10个是报错, can't read "node_(5)": no such element in array while executing "$ns_ attach-agent $node_(5) $null_(1)" (file "cbr_n5_m5" line 25) invoked from

TCP协议的NS2仿真

# # ftp # \ # tcp sink # \ / # n0--------5M 2ms---------n1 # # set ns [new Simulator] set f [open out.tr w] $ns trace-all $f set nf [open out.nam w] $ns namtrace-all $nf proc finish {} { global ns nf f $ns flush-trace close $f close $nf exec nam out.

NS2仿真环境安装

eclipse 的安装 sudo apt-get install eclipse sudo apt-get install eclipse-cdt NS2安装 1.下载软件 首先先下载ns-allinone-2.35.tar.gz(http://sourceforge.net/projects/nsnam/files/), 将其放到/home/administrator/zhouhui/soft/下(zhouhui是我的文件名,soft是我建立的一个文件夹) 打开终端(Ctrl+Alt+T),在

Java简单类——多对多映射

1 class Item { // 父栏目 2 private int iid ; 3 private String name ; 4 private String note ; 5 private Subitem subitems [] ; //一个父栏目下有多个子栏目 6 private Product products [] ; //一个栏目下包含多个商品 7 public Item(int iid,String name,String note) { 8 this.iid = iid ;

UDP协议下的NS2仿真

来自simple.tcl set ns [new Simulator] $ns color 0 blue$ns color 1 red$ns color 2 white set n0 [$ns node]set n1 [$ns node]set n2 [$ns node]set n3 [$ns node] set f [open out.tr w]$ns trace-all $fset nf [open out.nam w]$ns namtrace-all $nf $ns duplex-link

FTP简单的大文件传输

服务器端 # import socket# import struct# import json# sk = socket.socket()# sk.bind(("127.0.0.1",8090))# sk.listen()# buffer = 1024# conn,addr = sk.accept()# head_len = conn.recv(4)# head_len = struct.unpack("i",head_len)[0]# json_head = c

Socket传输简单的信息以及粘包问题的解决

一.简单的socket程序--传输简短文字: # -*- coding: utf-8 -*- # -*- Author: WangHW -*- import socket whw_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) whw_client.connect(('127.0.0.1',9001)) while 1: cmd = input('>>>:').strip() if not cmd: continue w

功能分享丨超简单快速文件传输方式

如何进行文件存储,长久以来一直是各职场人或多或少会面临的难题,过多的存储在办公电脑中,容易造成卡顿进而影响工作效率,因此,办公文档存在哪里比较合适?百度云?OneDrive?Google Drive?Dropbox?上述云服务产品相信各位职场人员都不陌生,或多或少使用过.听说过.了解过.也是现阶段提供服务较为全面的产品,这些产品的知名度较大,是用户比较普遍能接受使用的产品.这类较为常用产品存在许多限制,影响用户体验. 上传下载限速问题,由于速度受限,存取文件时间过长,影响工作效率 存储空间受限,