翻译大师的博客

讲述翻 译大师学习翻译的心路历程

« void B_DictionaryCapacity3. 多个参数逗号分隔 »

14 #include &quot

在这一部分,我将给处以个可以在ns上应用 的新协议的例子.你应该 在此之前相对熟悉ns,而且一些c++知识也是相对必须的.你也应该至少读过"ns注释和文档 "(现在叫做手册)的3.1-3.3章节来理解Tcl和C++之间的交互.
这一部 分的代码实现了简单的lpingr协议(灵感来自"ns注释和文档 "(现在叫做手册)的9.6章节,但是这个相对困难).一个节 点将会可以发送一个包到另一个节点,包还会快速的回传,这样来 计算一次来回的时间.
我知道 这里给出的代码可能不是最好的实现,我也确 信它能够被改进,但是我 希望它能够容易被理解,这就是 这篇文章的主要目的.一些建议可以发送到:ns-users@isi.edu.
1.头文件
在一个新的头文件lping.hr中,我们首 先需要说明新的ping包头部的数据结构,这将用 来携带相关的数据.
1 struct hdr_ping {
2 char ret;
3 double send_time;
字符类型lretr,如果包 由来自发送方到被ping的节点 时将会被设置为l0r,在返回的路上,它将会被设置为l1r.double类型的lsend_timer是一个时间戳,发送的时候设置,将会被 用来计算来回的时间.
下面的代码声明了lPingAgentr类,它是lAgentr类的子类.
1 class PingAgent : public Agent {
2 public :
3 PingAgent();
4 int command( int argc, const char * const * argv);
5 void recv(Packet * , Handler * );
6 protected :
7 int off_ping_;
接下来的部分,我将会给出定义lPingAgent()r/lcommand()r和'recv()'的C++代码,这些在 声明中都重定义.int型的loff_ping_r将用来进入包的ping的头部.注意局 部变量通常使用到'_'.
附(整体代码):
2 * File: Header File for a new 'Ping' Agent Class for the ns
3 * network simulator
4 * Author: Marc Greis (greis@cs.uni-bonn.de), May 1998
9 #ifndef ns_ping_h
10 #define ns_ping_h
12 #include " agent.h "
13 #include " tclcl.h "
14 #include " packet.h "
15 #include " address.h "
16 #include " ip.h "
19 struct hdr_ping {
20 char ret;
21 double send_time;
25 class PingAgent : public Agent {
26 public :
27 PingAgent();
28 int command( int argc, const char * const * argv);
29 void recv(Packet * ,, Handler * );
30 protected :
31 int off_ping_;
35 #endif
2.C++代码
首先,C++和Tcl代码之 间的连接需要被定义.你不需 要完全理解这些代码,但是如 果还没有理解的话可以去阅读"ns手册"3.1-3.3节.
1 static class PingHeaderClass : public PacketHeaderClass {
2 public :
3 PingHeaderClass() : PacketHeaderClass( " PacketHeader/Ping " , sizeof (hdr_ping)) {}
5 } class_pinghdr;
8 static class PingClass : public TclClass {
9 public :
10 PingClass() : TclClass( " Agent/Ping " ) {}
11 TclObject * create( int , const char * const * ) {
12 return ( new PingAgent());
14 } class_ping;
接下来 的代码段构造了lPingAgentr类.它连接了需要在Tcl和C++中使用的变量.
1 PingAgent::PingAgent() : Agent(PT_PING)
3 bind( " packetSize_ " , & size_);
4 bind( " off_ping_ " , & off_ping_);
lCommand()r函数在对于'PingAgent'类的Tcl命令执行时被执行.在我们的例子中,这就是l$pa sendr(假定lpar是一个Agent/Ping类的实例),因为我们想从Agent到其他Agent发送ping包.你最起 码应该将这些命令放入lcommand()r函数中,如果没 有找到这个匹配,你不得 不连同参数将命令传递到基类的lcommand()r(在这里就是lAgent::command()r).因为它的注释比较多,代码可 能看起来比较长.
1 int PingAgent::command( int argc, const char * const * argv)
3 if (argc == 2 ) {
4 if (strcmp(argv[ 1 ], " send " ) == 0 ) {
5 // Create a new packet
6 Packet * pkt = allocpkt();
7 // Access the Ping header for the new packet:
8 hdr_ping * hdr = (hdr_ping * )pkt -> access(off_ping_);
9 // Set the 'ret' field to 0, so the receiving node knows
10 // that it has to generate an echo packet
11 hdr -> ret = 0 ;
12 // Store the current time in the 'send_time' field
13 hdr -> send_time = Scheduler::instance().clock();
14 // Send the packet
15 send(pkt, 0 );
16 // return TCL_OK, so the calling function knows that the
17 // command has been processed
18 return (TCL_OK);
21 // If the command hasn't been processed by PingAgent()::command,
22 // call the command() function for the base class
23 return (Agent::command(argc, argv));
lrecv()r函数定 义了接收包时的动作.如果lretr是0,包的lsend_timer值不变,但是lretr设为1,返回包.如果lretr为1,引发一个Tcl函数(需要用户在Tcl中定义).
1 void PingAgent::recv(Packet * pkt, Handler * )
3 // Access the IP header for the received packet:
4 hdr_ip * hdrip = (hdr_ip * )pkt -> access(off_ip_);
5 // Access the Ping header for the received packet:
6 hdr_ping * hdr = (hdr_ping * )pkt -> access(off_ping_);
7 // Is the 'ret' field = 0 (i.e. the receiving node is being pinged)?
8 if (hdr -> ret == 0 ) {
9 // Send an 'echo'. First save the old packet's send_time
10 double stime = hdr -> send_time;
11 // Discard the packet
12 Packet::free(pkt);
13 // Create a new packet
14 Packet * pktret = allocpkt();
15 // Access the Ping header for the new packet:
16 hdr_ping * hdrret = (hdr_ping * )pktret -> access(off_ping_);
17 // Set the 'ret' field to 1, so the receiver won't send another echo
18 hdrret -> ret = 1 ;
19 // Set the send_time field to the correct value
20 hdrret -> send_time = stime;
21 // Send the packet
22 send(pktret, 0 );
23 } else {
24 // A packet was received. Use tcl.eval to call the Tcl
25 // interpreter with the ping results.
26 // Note: In the Tcl code, a procedure 'Agent/Ping recv {from rtt}'
27 // has to be defined which allows the user to react to the ping
28 // result.
29 char out [ 100 ];
30 // Prepare the output to the Tcl interpreter. Calculate the round
31 // trip time
32 sprintf( out , " %s recv %d %3.1f " , name(),
33 hdrip -> src_.addr_ >> Address::instance().NodeShift_[ 1 ],
34 (Scheduler::instance().clock() - hdr -> send_time) * 1000 );
35 Tcl & tcl = Tcl::instance();
36 tcl.eval( out );
37 // Discard the packet
38 Packet::free(pkt);
下面将 给出整体的文件.最有意 思的部分应该是ltcl.eval()r函数,这里lrecvr函数被调用,这里使用被ping节点的ID号和来回时间(毫秒)作为参数.第4部分将 会给出如何编写此类功能.但是首先,一些其 他的文件需要先被编写,以确保ns可以编译通过.
附(整体代码):
2 * File: Code for a new 'Ping' Agent Class for the ns
3 * network simulator
4 * Author: Marc Greis (greis@cs.uni-bonn.de), May 1998
9 #include " ping.h "
12 static class PingHeaderClass : public PacketHeaderClass {
13 public :
14 PingHeaderClass() : PacketHeaderClass( " PacketHeader/Ping " ,
15 sizeof (hdr_ping)) {}
16 } class_pinghdr;
19 static class PingClass : public TclClass {
20 public :
21 PingClass() : TclClass( " Agent/Ping " ) {}
22 TclObject * create( int , const char * const * ) {
23 return ( new PingAgent());
25 } class_ping;
28 PingAgent::PingAgent() : Agent(PT_PING)
30 bind( " packetSize_ " , & size_);
31 bind( " off_ping_ " , & off_ping_);
35 int PingAgent::command( int argc, const char * const * argv)
37 if (argc == 2 ) {
38 if (strcmp(argv[ 1 ], " send " ) == 0 ) {
39 // Create a new packet
40 Packet * pkt = allocpkt();
41 // Access the Ping header for the new packet:
42 hdr_ping * hdr = (hdr_ping * )pkt -> access(off_ping_);
43 // Set the 'ret' field to 0, so the receiving node knows
44 // that it has to generate an echo packet
45 hdr -> ret = 0 ;
46 // Store the current time in the 'send_time' field
47 hdr -> send_time = Scheduler::instance().clock();
48 // Send the packet
49 send(pkt, 0 );
50 // return TCL_OK, so the calling function knows that the
51 // command has been processed
52 return (TCL_OK);
55 // If the command hasn't been processed by PingAgent()::command,
56 // call the command() function for the base class
57 return (Agent::command(argc, argv));
61 void PingAgent::recv(Packet * pkt, Handler * )
63 // Access the IP header for the received packet:
64 hdr_ip * hdrip = (hdr_ip * )pkt -> access(off_ip_);
65 // Access the Ping header for the received packet:
66 hdr_ping * hdr = (hdr_ping * )pkt -> access(off_ping_);
67 // Is the 'ret' field = 0 (i.e. the receiving node is being pinged)?
68 if (hdr -> ret == 0 ) {
69 // Send an 'echo'. First save the old packet's send_time
70 double stime = hdr -> send_time;
71 // Discard the packet
72 Packet::free(pkt);
73 // Create a new packet
74 Packet * pktret = allocpkt();
75 // Access the Ping header for the new packet:
76 hdr_ping * hdrret = (hdr_ping * )pktret -> access(off_ping_);
77 // Set the 'ret' field to 1, so the receiver won't send another echo
78 hdrret -> ret = 1 ;
79 // Set the send_time field to the correct value
80 hdrret -> send_time = stime;
81 // Send the packet
82 send(pktret, 0 );
83 } else {
84 // A packet was received. Use tcl.eval to call the Tcl
85 // interpreter with the ping results.
86 // Note: In the Tcl code, a procedure 'Agent/Ping recv {from rtt}'
87 // has to be defined which allows the user to react to the ping
88 // result.
89 char out [ 100 ];
90 // Prepare the output to the Tcl interpreter. Calculate the round
91 // trip time
92 sprintf( out , " %s recv %d %3.1f " , name(),
93 hdrip -> src_ >> Address::instance().NodeShift_[ 1 ],
94 (Scheduler::instance().clock() - hdr -> send_time) * 1000 );
95 Tcl & tcl = Tcl::instance();
96 tcl.eval( out );
97 // Discard the packet
98 Packet::free(pkt);
3.必要的改变
如果你 想添加一个新协议的话,你将会需要改变一些ns源文件,尤其是 如果它使用了一个新的包格式.我建议 你对这些改变做上注释,使用#ifdef等等,这样的 话你就能够容易移除你的改变或者移植到心的ns版本上.
我们接下来需要为ping agent弄一个新的包类型,所以第 一步是编辑文件lpacket.hr.那里,你可以发现包协议的ID的定义(比如PT_TCP,PT_Telnet等等).为PT_PING在那里 添加一个新的定义.在我编辑的packet.h版本中,enum packet_t{}的最后 几行是下面的代码(它也许 看起来和之前或者以后的版本有些不同).
1 enum packet_t {
2 PT_TCP,
3 PT_UDP,
5 // insert new packet types here
6 PT_TFRC,
7 PT_TFRC_ACK,
8 PT_PING, // packet protocol ID for our ping-agent
9 PT_NTYPE // This MUST be the LAST one
你也需 要在这个文件里编辑p_info()来增加"Ping".
1 class p_info {
2 public :
3 p_info() {
4 name_[PT_TCP] = " tcp " ;
5 name_[PT_UDP] = " udp " ;
7 name_[PT_TFRC] = " tcpFriend " ;
8 name_[PT_TFRC_ACK] = " tcpFriendCtl " ;
10 name_[PT_PING] = " Ping " ;
12 name_[PT_NTYPE] = " undefined " ;
记住,在lmaker之前你需要做一个lmake dependr,否则这 两个文件不会再编译.
文件ltcl/lib/ns-default.tclr也需要被编辑.这个文 件定义了所有定义的Tcl类的缺省值.添加下面几行来设置Agent/Ping包的缺省大小.
1 Agent / Ping set packetSize_ 64
你也需要在文件ltcl/lib/ns-packet.tclr添加新ping包的入口,在文件开始的列表中.它是以下的代码.
1 { SRMEXT off_srm_ext_}
2 { Ping off_ping_ }} {
3 set cl PacketHeader / [lindex $pair 0 ]
最后的改变是lMakefiler.你需要添加文件lping.or到类文件列表.在我的版本中,最后几行改成如下:
1 sessionhelper.o delaymodel.o srm - ssm.o \
2 srm - topo.o \
3 ping.o \
4 $(LIB_DIR) int .Vec.o $(LIB_DIR) int .RVec.o \
5 $(LIB_DIR)dmalloc_support.o \
你现在可以重编译ns,只需要在ns目录中打入lmaker.如果你有问题,杭州翻译公司,请电邮作者.
4.Tcl代码
下面写出了lrecvr过程(在C++中lrecv()r函数中调用,在ping包被接收时):
1 Agent / Ping instproc recv {from rtt} {
2 $self instvar node_
3 puts " node [$node_ id] received ping answer from \
4 $from with round-trip-time $rtt ms. "
这个代 码应该比较容易理解.唯一的 新的东西是它使用了基类lAgentr的变量lnode_r来获取agent依附的节点的节点ID.
附(完全代码):
1 # Create a simulator object
2 set ns [new Simulator]
4 # Open a trace file
5 set nf [ open out . nam w]
6 $ns namtrace - all $nf
8 # Define a 'finish' procedure
9 proc finish {} {
10 global ns nf
11 $ns flush - trace
12 close $nf
13 exec nam out . nam &
14 exit 0
17 # Create three nodes
18 set n0 [ $ns node]
19 set n1 [ $ns node]
20 set n2 [ $ns node]
22 # Connect the nodes with two links
23 $ns duplex - link $n0 $n1 1Mb 10ms DropTail
24 $ns duplex - link $n1 $n2 1Mb 10ms DropTail...
  • 相关文章:

发表评论

网站分类

文章归档

Tags

Powered By
Copyright 杭州翻译公司 杭州翻译. Some Rights Reserved.

友情链接:    多人斗牛在线   开户彩票网站   彩票网上购买恢复了吗   多人斗牛app   3号彩票网站