简单的多对一传输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代码如下:
# by jiqing 2007-6-6
set ns [new Simulator]
#color
$ns color 1 Blue
$ns color 2 Red
$ns color 3 Green #open a nam trace file
set nf [open out.nam w]
$ns namtrace-all $nf #open a trace file
set tf [open out.tr w]
$ns trace-all $tf #finish procedure proc finish {} {
global ns nf tf
$ns flush-trace
close $nf
close $tf
exec ./nam out.nam & exit 0
} #create nodes
set node_(s1) [$ns node]
set node_(s2) [$ns node]
set node_(s3) [$ns node]
set node_(r) [$ns node] #create links
$ns duplex-link $node_(s1) $node_(r) 1Mb 10ms DropTail
$ns duplex-link $node_(s2) $node_(r) 1.5Mb 10ms DropTail
$ns duplex-link $node_(s3) $node_(r) 1Mb 10ms DropTail #relayout
$ns duplex-link-op $node_(s1) $node_(r) orient right-down
$ns duplex-link-op $node_(s2) $node_(r) orient right
$ns duplex-link-op $node_(s3) $node_(r) orient right-up #add udp agents
set udp_(s1) [new Agent/JiqingUDP]
$ns attach-agent $node_(s1) $udp_(s1)
set udp_(r1) [new Agent/JiqingUDP]
$ns attach-agent $node_(r) $udp_(r1)
$ns connect $udp_(s1) $udp_(r1) $udp_(s1) set fid_ 1 $udp_(r1) set fid_ 1
set udp_(s2) [new Agent/JiqingUDP]
$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的源代码。
简单的多对一传输ns2仿真的更多相关文章
- NS2仿真:使用NS仿真软件模拟简单网络模型
NS2仿真实验报告1 实验名称:使用NS仿真软件模拟简单网络模型 实验日期:2015年3月2日~2015年3月7日 实验报告日期:2015年3月8日 一.实验环境(网络平台,操作系统,网络拓扑图) 运 ...
- NS2仿真:公交车移动周期模型及性能分析
NS2仿真实验报告3 实验名称:公交车移动周期模型及性能分析 实验日期:2015年3月16日~2015年3月21日 实验报告日期:2015年3月22日 一.实验环境(网络平台,操作系统,网络拓扑图) ...
- NS2仿真:两个移动节点网络连接及协议性能分析
NS2仿真实验报告2 实验名称:两个移动节点网络连接及协议性能分析 实验日期:2015年3月9日~2015年3月14日 实验报告日期:2015年3月15日 一.实验环境(网络平台,操作系统,网络拓扑图 ...
- 网络拥塞控制与NS2仿真
准备工作: 1. 安装virtual box 虚拟机,并安装虚拟机增强功能,并配制共享文件夹. 共享文件夹自动挂载后的路径为/media/sf_xxx文件夹,xxx为所起的文件名. 解决virtual ...
- 分享CCNTFS小工具,在 macOS 中完全读写、修改、访问Windows NTFS硬盘的文件,无须额外的驱动(原生驱动)更稳定,简单设置即可高速传输外接NTFS硬盘文件
CCNTFS [ 下载 ] 在 macOS 中完全读写.修改.访问Windows NTFS硬盘的文件,无须额外的驱动(原生驱动)更稳定,安装后进行简单设置即可高速传输外接NTFS硬盘文件,可全程离线使 ...
- 简单实现一个快速传输电子书到kindle的小项目
前言 最近翻出来好久没有看的kindle,准备继续我的阅读之路.当然,也是因为发现了一个非常好的获取电子书资源的网站,又燃起了我的阅读兴趣. 然而,往kindle里传输电子书的方式一共有四种: 直接在 ...
- Java简单类——多对多映射
class Admin { private String aid ; private String password ; private Role role ; public Admin(String ...
- 【NS2仿真】RTP协议安装
来自: http://personales.upv.es/fboronat/Research/NS2_RTP/NS2_RTP_RTCP_module.htm 文件:http://pan.baidu.c ...
- 【NS2仿真】TCP与UDP混合
# # ftp # \ # tcp # \ # n0 sink # \ / # \ / # n1---5M 2ms---n3 # / \ # / \ # n2 null # / # udp # / # ...
随机推荐
- linux安全配置学习
参考摘自https://www.cnblogs.com/hiccup/p/4300963.html 1.关闭icmp请求 #vm虚拟机是130地址,通过echo 1 > /proc/sys/ne ...
- SVM (support vector machine)
简单原理流程转自:http://wenku.baidu.com/link?url=57aywD0Q6WTnl7XKbIHuEwWENnSuPS32QO8X0a0gHpOOzdnNt_K0mK2cucV ...
- ubuntu下安装软件的三种方法
在ubuntu当中,安装应用程序常用的三种方法,分别是apt-get,dpkg安装deb和make install安装源码包三种. apt-get方法 使用apt-get install来安装应用程序 ...
- LInux查看网速带宽及各进程占用情况:nethogs
安装: #Ubuntu: sudo apt-get install nethogs #CentOS: sudo yum install nethogs 使用: $ sudo nethogs
- java 数据结构与算法---链表
原理来自百度百科 一.链表的定义 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运 ...
- UVAlive3523_Knights of the Round Table
圆桌骑士.有的骑士之间是相互憎恨的,不能连坐,需要安排奇数个骑士围着桌子坐着,大于3个,求哪些骑士不可能安排到座位. 根据给定的关系,如果两个骑士之间没有憎恨关系,那么连边.最终就是求有多少个点无法位 ...
- Python学习---日期时间
在Python里面日期时间的功能主要由几个模块提供:time,calendar,datetime,date等 time主要用到的功能函数: #!/usr/bin/python3 # coding:ut ...
- zabbix短信(阿里云短信平台)与邮件报警
环境说明 操作系统 centos7 zabbix_server zabbix 4.0.3 python 3.6.5 短信平台 阿里云短信 zabbix_server配置信息 1 [root@cp-hb ...
- C 输入 & 输出——Day03
当我们提到输入时,这意味着要向程序填充一些数据.输入可以是以文件的形式或从命令行中进行.C 语言提供了一系列内置的函数来读取给定的输入,并根据需要填充到程序中. 当我们提到输出时,这意味着要在屏幕上. ...
- How Many Points? LightOJ - 1077(线段经过整点个数与gcd 证明)
题意: 已知两点 (x1,y1) 和 (x2, y2)求两点间线段上的整点的个数 解析: 就是求gcd(abs(x2- x1),abs(y2 - y1)) 证明: 我们分水平方向和竖直方向两个方向看 ...