RFC6206 中描述的涓流(Trickle)算法建立了一种能够感知网络流量大小的本地通信机制,通过底层一致性模型引导节点的发送来实现节点间的高效数据同步。当某个节点发现与邻居节点的路由信息不一致时,算法会引导节点通过快速(毫秒级)通信实现路由信息的同步。当同步完成,节点间的数据达到一致时,节点会以指数级降低数据发送频度,从而发送非常少的帧(大概每小时几个数据分组)。与广泛采用的洪泛(flooding)机制相比,通过控制发送速率,避免向网络发送大量的帧,这样,网络节点仅会接收到足够保持网络一致性的少量的帧。进一步讲,由于只依赖本地通信(广播或本地多播),该算法能够完成网络重建,对于网络拓扑变化快、易丢包和易中断的网络也非常稳健,易于实现,并且只需要维护很少的状态。另一重要特点是当前的涓流算法实现只需要使用4~11字节内存,50~200行C代码。
1.涓流定时器
Contiki 操作系统涓流库包含用于实现涓流算法的函数,涓流算法构成了涓流定时器运行的基础。涓流库包含涓流定时器使用的功能细节。涓流算法用于检查系统中存在的信息是否有任何变化,当检测到这种变化时,采取足够的措施以解决信息不一致性的问题。
涓流算法中有3 个参数: IMIN、IMAX 和k。其中,IMIN 是最小周期大小,定义IMAX 为IMIN 的2 的n 次方倍,例如定义IMAX 为16,如果IMIN 为100 ms,那么IMAX 定义的时间就是100×216ms,k 是冗余常数。涓流算法中使用了3 个变量:I、c 和t。其中,I 定义当前周期的大小,t 表示当前周期内的一个时间,c表示计数器。
图8-3简要描述了涓流算法的工作原理。
图8-3 涓流算法
在启动定时器之前,设置IMIN 值的范围为[I/2,I]。计数器变量(c)帮助跟踪系统状态的一致性。如果系统状态一致,则计数器递增,否则重置。变量c 的值必须始终小于k(称为冗余常数),当计时器到期时,重置涓流计时器值为IMIN,否则它被加倍。必须检查新的当前周期I是否在上述范围内,甚至可以使节点在需要时抑制不一致性。一般建议不要这样处理,但对于少数应用程序可能需要通过设置k=0来禁用抑制。
涓流定时器可用于多种应用场合,大多数应用程序可能需要定期检查节点是否有新信息,这一般是在版本号的帮助下完成的,如果检测到信息不一致,则表示该节点没有最新信息,需要更新其信息。RPL 协议是使用涓流计时器的示例协议,RPL协议具有用于发送和接收消息的DIO和DAO消息,DIO消息源自接收器,而DAO 消息源自节点。这个涓流定时器帮助跟踪接收器在告诉节点“我是接收器”时发送消息。在RPL 协议中,会定期发送DIO 消息,并且每次传输后发送该消息的时间间隔都会增加,这是在涓流计时器的帮助下完成的。
涓流定时器的定义在程序文件trickle_timer.h 和trickle_timer.c 中,这两个程序文件保存在core/lib 文件夹中,这两个文件中定义的协议实现调用的函数如下:
Contiki 系统涓流库实现的定时器符合RFC 6206 中描述的涓流算法,希望使用涓流定时器的协议可以直接使用该库而不需要在其内部实现涓流算法。协议实现将声明struct trickle_timer 类型的一个(或多个)变量,然后通过调用trickle_timer_config()函数对其参数执行操作,trickle_timer_set()函数将启动定时器。当定时器到达当前涓流间隔内的时间t时,涓流库将调用协议提供的回调函数,该回调函数将向协议发送信号,通知当前时间是执行发送数据TX的时间(参见RFC 中的算法步骤4)。协议不需要检查抑制条件,涓流库完成该检查操作。如果必须抑制数据发送TX,则根本不会调用回调。涓流库还提供了当协议听到“一致”或“不一致”消息时以及发生“外部事件”时调用的函数。
2.涓流定时器应用举例
(www.xing528.com)
图8-4 网络拓扑图
Contiki操作系统提供了涓流定时器的应用示例trickle-library.c,该程序代码保存在examples/trickle-library/文件夹中。另外,该文件夹中的仿真脚本trickle-library.csc 定义了具有5 个传感器节点的无线传感器网络,每个传感器节点将运行trickle-library.c程序,运行时的网络拓扑图如图8-4所示。下面将简单解释该程序的代码:
程序trickle-library.c 的上面几行代码中,语句“static struct trickle_timer tt;”定义了指向涓流定时器结构体的指针tt,该结构体保存与涓流算法工作相关的各种字段。宏常量“IMIN”定义了变量I 可能的最小周期值,冗余常量“REDUNDANCY_CONST” 定 义 了 变 量 k 的 值 为 2。 宏 常 量“TRICKLE_PROTE_PORT”定义了涓流协议使用的端口号为30001。宏常量“NEW_TOKEN_INTERVAL” 定义了令牌的生成时间间隔“10 *CLOCK_SECOND”,而宏常量“NEW_TOKEN_PROB”定义生成新令牌的概率为2。这些值可以根据应用的需要进行更改。Contiki系统中定义了不同类型的定时器,第4章中我们详细说明了这些定时器,这里定义的定时器et用于周期性生成的不一致性。
上面创建线程的代码中,首先打开通信的本地端口,然后生成套接字,并将端口号与套接字绑定。令牌的初始值设置为0。通过调用函数trickle_timer_config(t,IMIN,IMAX,REDUNDANCY_CONST)处理该函数中的相关参数,调用函数trickle_timer_set(&tt,trickle_tx,&tt)启动定时器。定时器etimer用于定期生成“不一致”,这有助于确保系统处于正常工作状态,为确保正确处理这种不一致性,指定了事件处理程序tcpip_handler(),根据上面指定的周期,定时器etimer会定期触发不一致性。
当调用事件处理程序时,函数的控制转移到语句static void tcpip_handler(void)定义的tcpip_handler 函数,可以使用LED 灯来观察传输何时发生。在处理程序中,检查传输是否一致。如果节点具有新令牌,则会触发不一致,并通过重置计时器来更新令牌。定时器到达指定时间时会触发回调,涓流库提供此回调。涓流库依赖于涓流定时器以及其他计时器,如etimer、stimer、ctimer 和rtimer。涓流定时器的定义在trickle-timer.c 文件中。在不一致的情况下,函数void trickle_timer_inconsistency(struct trickle_timer*tt)将调用涓流库并要求它根据不一致的类型重置定时器。在一致的状态下,计数器递增,由函数void trickle_timer_consistency(struct trickle_timer*tt)实现。所有用于设置参数值的函数都在trickle-timer.c中定义。
图8-5和图8-6分别展示了涓流协议的启动过程和运行过程。
图8-5 涓流协议启动
图8-6 涓流协议运行
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。