转自:http://blog.csdn.net/delphiwcdj/article/details/4810705#
代理
代理(Agent)可以构建和销毁网络层的分组,是网络层分组的起点和终点,同时,代理还可以实现各种不同层的网络协议。
例如:
NS2中的Agent/TCP和Agent/UDP分别实现了传输层的两个重要协议即TCP和UDP。
注意:
(1)在NS2中,所有的OTcl类都是从SplitObject类一级级继承出来的,NS2使用了一种以字符“/”作为分割符的类命名规则来表示一个OTcl类从SplitObject开始的继承关系。
[1] Agent类
Agent类是由C++和OTcl共同实现的。
对于代理的使用者来说,只需知道使用此特定代理的OTcl Agent中的内部变量。
例如:
OTcl中的Agent/UDP类内部变量packetSize_实际上是与C++中的UDP Agent中的size_绑定在一起的,只需创建一个Agent/UDP对象,并使用set命令设置packetSize_的值,这时,packetSize_的值将自动赋给C++ Agent类中size_变量。
注意:
NS2支持的各种协议代理,每一种协议代理都是Agent类的子类。
[2] UDP代理
(1)UDP协议
(a)是一种无连接的传输层协议,提供面向事物的简单的不可靠的信息传送服务;
(b)UDP没有流量控制机制,收到分组时也不对分组进行确认;
(C)UDP适用于一次只传送少量数据、对可靠性要求不高的应用环境;
(d)UDP对应的应用层协议,包括网络文件系统(NFS)、简单网络管理协议(SNMP)、域名系统(DNS)以及简单文件传输协议(TFTP)
(2)Agent/UDP
Agent/UDP类是Agent类的一个子类,模拟了UDP协议的主要功能。
NS2创建和设置UDP代理可以分为以下几步:
<步骤1> 创建一个Agent/UDP对象并将其绑定到相应的节点上作为分组的发送器。
<步骤2> 设置Agent/UDP的部分内部变量。
<步骤3> 创建一个Agent/Null对象并将其绑定到相应的节点作为分组的接收器。
<步骤4> 在两个发送和接受代理之间创建connect连接。
Tcl代码
- #创建UDP代理,假设节点n0和n1,以及模拟器对象ns已经建立
- set udp0 [new Agent/UDP] ;#创建一个UDP Agent
- $ns attach-agent $n0 $udp0 ;#将UDP Agent绑定在节点n0上,作为分组的发送器
- $udp0 set packetSize_ 536 ;#设置UDP数据分组大小为536字节
- set null0 [new Agent/Null] ;#创建一个空代理对象null0,作为分组的接收器
- $ns attach-agent $n1 $null0 ;#把null0绑定在节点n1上
- $ns connect $udp0 $null0 ;#在两个Agent之间建立连接
注意:
Agent/Null是空代理类,它通常和UDP代理配合使用,作为数据的接受者。空代理将接收到的分组不做任何处理直接丢弃。这一点说明空代理作为UDP代理的接收器是合适的,因为UDP协议是一种无连接的不可靠的协议,它并不要求接收端对分组做出任何响应。
[3] TCP代理
(1)TCP协议
(a)TCP协议即传输控制协议,提供了一个完全可靠(没有数据重复或丢失)、端到端的、面向连接的、全双工的字节流服务,允许两个应用进程建立一个连接,并在任何一个方向上发送数据,然后终止连接;
(b)每一个TCP连接可靠地建立,友好地终止,在终止前所有数据都会被可靠地传输;
(c)TCP使用“三次握手”的方式建立一个连接,数据传输完成之后,任何一方都可以断开连接;也就是说,一个应用进程开始传送数据到另一个应用进程之前,它们之间必须建立连接,需要相互传送一些必要的参数,以确保数据的正确传输;
(d)TCP协议确保通过一个连接发送的数据能够被接收端正确无误地接收,且不会发生数据丢失或乱序;
TCP使用以下机制确保服务的可靠性:
(a)选择合适发送的数据块大小,并赋予序列号
TCP连接一旦建立,应用程序就不断地把数据先发送到TCP发送缓冲区(TCP sendbuffer),接下来,TCP就把数据流分成块,再添加TCP协议的头部(TCP header)形成TCP报文段。这样就将应用程序数据封装成了传输协议数据单元(TPDU)。这些报文段送到网络层,由IP协议封装成IP数据报之后发送到网络上。
(b)对发送的TPDU启动计时器,超时重发
当TCP发出一个报文段后,就启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。可以根据不同需要设定各种重传策略。
(c)对正确接收的TPDU进行确认
当TCP收到发自TCP连接另一端的报文段后,将发送一个确认。这个确认不是立即发送的,通常要推迟(为什么?)。
(d)识别并丢弃重复的TPDU
既然TCP报文段封装成IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据报进行重新排序,将收到的数据报以正确的顺序交给应用层。由于IP数据报会发生重复,因此TCP的接收端必须丢弃重复的TPDU。
(e)提供流量控制(实行缓冲区管理)
TCP协议采用滑动窗口机制实现流控。窗口的大小表示在最近收到的确认号之后允许传送的数据长度。连接双方的主机都为TCP连接分配了一定数量的缓存。每当进行TCP连接时,接收端主机只允许发送端主机发送的数据不大于其缓存空间的大小。也就是说,数据传输的流量大小由接收端确定。如果没有流量控制,发送端主机就可能以比接收端主机快得多的速度发送数据,使得接收端的缓存出现溢出。
(2)Agent/TCP
NS2中有两类TCP代理:单向代理(one-way agent)和双向代理(two-way agent)
(a)单向代理包括一系列的TCP发送者(依照拥塞算法和差错控制算法的不同)和接受者(TCPSink)。
(b)双向代理本身既可以作为发送者也可以作为接受者。
主要考虑TCP的单向代理,以Agent/TCP(Tahoe TCP)和Agent/TCPSink为例。
NS2创建和设置TCP代理可以分为以下几步:
<步骤1> 创建一个Agent/TCP对象,作为分组的发送器。
<步骤2> 设置Agent/TCP对象的部分内部变量。
<步骤3> 创建一个Agent/TCPSink对象,作为分组的接收器。
<步骤4> 在发送和接受代理之间创建connect连接。
Tcl代码
- #创建TCP代理,假设节点n0和n1,以及模拟器对象ns已经建立
- set tcp [new Agent/TCP] ;#创建一个TCP源代理对象tcp
- $ns attach-agent $n0 $tcp ;#把这个TCP源代理绑定在节点n0上
- $tcp set fid_ 1 ;#设置IP层数据流fid
- $tcp set window_ 20 ;#设置TCP滑动窗口的大小为20
- set sink [new Agent/TCPSink] ;#创建分组的接收代理对象
- $ns attach-agent $n1 $sink ;#将接收器sink代理绑定到节点n1上
- $ns connect $tcp $sink ;#在两个Agent之间建立连接
注意:
在单向代理中,TCP源代理负责发送TCP数据分组,而TCPSink对象负责接收数据分组,并发送确认ACK分组,可以通过设置packetSize_的值来设置所有ACK分组的大小。
[4] 其他协议Agent
NS2中除了支持UDP、TCP协议外,还支持许多其他的协议,这些协议都是通过继承Agent来实现的。
#查看NS2支持的各种协议的Agent
- proc showAgent {arg} {
- foreach c [$arg info subclass] {
- puts $c
- if {[$c info subclass] != ""} {
- showAgent $c
- }
- }
- }
- showAgent "Agent"
[5] 与Agent相关的命令
set agent [new Agent/AgentType] ;#创建一个新的代理对象
$n attach-agent <node> <agent> ;#在<node>上绑定一个<agent>,假定<agent>已经创建
$agent port ;#返回绑定的agent端口号
$agent dst-port ;#返回目标端口号
$agent attach-app <s_type> ;#在agent上绑定一个类型为<s_type>应用
$ns connect <src> <dst> ;#在src和dst之间创建一条连接,假定src和dst代理已经创建
$ns create-connect <srctype> <src> <dsttype> <dst> <pktclass> ;在两个代理之间创建一条完整的连接
$agent attach-trace <file> ;#将<file>绑定到agent上,允许Nam对Agent事件的跟踪