(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代码
[python]view plaincopyprint?
?? #创建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] 其他协议AgentNS2中除了支持UDP、TCP协议外,还支持许多其他的协议,这些协议都是通过继承Agent来实现的。 #查看NS2支持的各种协议的Agent [python]view plaincopyprint?
?? proc showAgent {arg} {
?? foreach c [$arg info subclass] { ?? puts $c
?? if {[$c info subclass] != \ ?? showAgent $c ?? } ?? } ?? }
?? showAgent \
[5] 与Agent相关的命令
set agent [new Agent/AgentType] ;#创建一个新的代理对象
$n attach-agent
经创建
$agent port ;#返回绑定的agent端口号 $agent dst-port ;#返回目标端口号
$agent attach-app
$ns create-connect
$agent attach-trace
第九讲 应用层
在NS2中,业务流是由应用层产生的。
[1] 应用层概述
在NS2中,应用层程序构建在传输层之上,它分为两大类:流量产生器(traffic generator)和应用模拟器(simulated application)。 注意:
(1)流量产生器一般用在UDP代理之上;应用模拟器一般用在TCP代理之上。 (2)NS2通过在传输层Agent内部预定义一些成员函数来模拟socket API的功能。
(3)Application类是OTcl中应用层程序的基类,提供了应用层程序的一些行为的基本原型。 (4)可以通过Tcl代码查看NS2中能够实现的各种应用程序。(P.61)
[2] 流量产生器(Traffic generators) 网络中的业务流是随机产生的,因此,以某个固定速率来模拟实际业务流的产生情况显然是不合适的。为此,NS2中创建了各种不同的概率模型来模拟产生实际网络中的业务流。 在NS2中,根据业务流产生的概率模型的不同,实现了4种流量产生器(一般都是建立在UDP代理之上)。
(1)指数分布流量产生器
在OTcl中对应的类名为Application/Traffic/Exponential。 该流量产生器按照指数On/Off分布产生数据。在\阶段,分组以固定的速率发送;在\阶段,分组停止发送。\和\两种状态的时间都符合指数分布。 (2)泊松分布流量产生器
在OTcl中对应的类名为Application/Traffic/Pareto。
该发生器除了\、\两种状态之间的时间产生业务流符合Pareto分布外,其他时间按指数On/Off分布。这种分布可用来产生长时间相关的急剧通信量。 (3)固定比特流量产生器
在OTcl中对应的类名为Application/Traffic/CBR。 该流量产生器按照一个固定的速率产生业务流,分组的长度为一常数值,可以选择需要时对分组发送的时间间隔产生随机抖动。 (4)Trace文件流量产生器
在OTcl中对应的类名为Application/Traffic/Trace。
该流量产生器按照一个Trace文件产生数据。 例子:
?? #在UDP上配置一个CBR流量发生器的的基本步骤
?? #假设模拟器对象ns、节点n0和n1已经创建,数据流从n0到n1 ??
?? #创建传输层代理对象并将传输层代理绑定到相应的节点上 ?? set src [new Agent/UDP] ?? set sink [new Agent/Null] ?? $ns attach-agent $n0 $src ?? $ns attach-agent $n1 $sink ??
?? #创建流量产生器对象,设置对象属性(可选),并将其与传输层的源代理绑定 ?? set e [new Application/Traffic/CBR] ;#创建一个流量产生器对象 ?? $e set packetSize_ 300 ;#设定数据分组的大小为300字节 ?? $e set rate_ 32kb ;#设定数据的发送速率为32kb
?? $e set random_ On ;#在分组的发送时间上加入随机“噪声” ?? $e attach-agent $src ;#将流量产生器对象与源代理绑定 ??
?? #启动和停止流量产生器
?? $ns at 0.0 \ ;#在0.0秒启动流量产生器 ?? $ns at 5.0 \ ;#在5.0秒停止流量产生器
[3] 应用模拟器(Simulated application)建立在TCP代理之上的业务流需要使用应用模拟器来产生。
(1)FTP应用模拟器
对应的OTcl类为Application/FTP。主要用来模拟大量数据的传送。 (2)Telnet应用模拟器
对应的OTcl类为Application/Telnet。 例子:
?? #在TCP上使用FTP ?? set src [new Agent/TCP] ??? set sink [new Agent/TCPSink] ??? $ns attach-agent $n0 $src ??? $ns attach-agent $n1 $sink
??? $ns connect $src $sink ;#在源代理和接收代理之间创建TCP连接 ???
??? set ftp [new Application/FTP] ??? $ftp attach-agent $src ??? $ns at 0.5 \
第十讲
数据的记录与动画演示
在模拟过程中,数据跟踪和采集的方法有多种,大体可以分为两大类:
(1)模拟的执行过程中直接显示跟踪数据
(2)将采集到的数据直接存放到一个文件中,以便后期的处理和分析(常用) 在NS2中有两种主要不同的数据监视器对象 (1)Trace
该对象详细地记录了模拟的整个过程,包括每一个数据分组到达、离开链路或队列,以及分组被丢弃等信息,并存储于Trace文件中。 (2)Monitor
用来记录各种有用的数值,比如到达、离开链路或队列的数据分组数、字节数等。 [1] Trace的使用
Trace的功能是能够详细地记录模拟过程,同时,用户也可以根据自己的需要记录模拟过程中的任何一个细节。 注意:
(1)NS2提供了各种不同的Trace类型,且都继承于OTcl的Trace类,实现不同的功能。 (2)可以通过Tcl代码查看NS2支持的各种Trace类(P.66) 在Tcl中使用Trace,分为两种情况:
(1)记录整个模拟过程的事件,将所有模拟细节都记录下来。 (2)根据需要记录模拟过程中的某些细节,记录一部分事件。
NS2的Simulator类内部定义了各种过程来支持Trace的使用,具体如下: (1) $ns trace-all
记录整个模拟过程,将模拟过程的所有数据写入Trace文件中,为Trace文件的文件句柄。
(2) $ns trace-queue
记录节点n1和n2间链路的事件,并将相关数据写入名为
(3) $ns flush-trace
清空模拟过程中所有Trace对象的缓冲区。 [2] Trace文件格式
在模拟有线网络时,得到默认的Trace文件的每条记录包含了以下12项:
Event|Time|From node|To node|Pkt Type|Pkt size|Flags|Fid|Src addr|Dst addr|Seq num|Pkt id (1)Event:发生事件的类型(四种) + :分组enqueue事件 - :分组dequeue事件 r :目的节点receive事件 d :队列drop(丢尾)事件 (2)Time:事件发生的时间
(3)From node:发送分组节点的id (4)To node:接收分组节点的id
(5)Pkt(packet:分组的缩写)Type:分组类型 (6)Pkt size:分组大小 (7)Flags:标志项 (8)Fid:流标识符
(9)Src addr:源地址,格式为node.port (10)Dst addr:目的地址,格式为node.port