本帖最后由 金鱼木鱼 于 2011-3-28 16:39 编辑
摘 要: uIP作为一种广泛使用的轻量级嵌入式TCP/IP协议栈,其UDP协议的实现还不够完善,目前最新的1.0版本中仅实现了UDP客户端,尚没有实现UDP服务端。为此,对其进行了以下三方面的改进:UDP服务端口的初始化;接收到UDP客户端数据包后的端口号判断及匹配;UDP服务端发送报文后目的端口的释放。经过以上改进后,实验证明,uIP 1.0中的UDP实现了服务端的功能。
关键词: uIP;嵌入式TCP/IP协议栈;UDP;端口
随着嵌入式技术、网络技术的发展,实现网络互联已经成为嵌入式系统发展的一个必然趋势。在目前的技术条件下,越来越多的嵌入式系统选择了TCP/IP作为与其他计算机系统互联的网络协议。嵌入式TCP/IP协议栈已经成为嵌入式系统研究与应用中的一个重要领域。
由于嵌入式系统的软硬件资源都较为有限,大多数嵌入式系统中运行的TCP/IP协议栈均根据嵌入式系统的特点进行了相应的裁剪。目前应用比较广泛的嵌入式TCP/IP协议栈有:ucTCP-IP、LWIP、uIP、Linux TCP/IP等。其中uIP是专为8 bit和16 bit的嵌入式微控制器设计的微型TCP/IP协议栈, 它具有良好的互操作性, 并遵循RFC标准。uIP协议栈的特点是具有很小的代码量,运行时需要的内存很少,实现了常用的TCP/IP协议;代码注释详尽,可以用于商业或非商业用途[1]。由于具有上述特点,uIP被广泛应用在嵌入式系统的网络互联中。
1 uIP协议栈的体系结构
在使用uIP的嵌入式系统的软件体系结构中,uIP协议栈相当于一个代码库,它通过一系列的函数实现与底层硬件和上层应用程序的通信。uIP协议栈与系统底层和上层应用之间的关系如图1所示[2]。
从图1可以看出,uIP协议栈主要提供了uip_input()和uip_periodic()2个函数供系统底层调用。uIP协议栈与应用程序的主要接口是UIP_APPCALL()和UIP_UDP_APPCALL()。
uIP初始化时调用uip_init()函数,它的主要功能是初始化协议栈的监听端口,并把所有连接设置为关闭状态。当网络控制芯片驱动程序接收到一个数据包时,驱动程序将数据包放入全局缓冲区uip_buf中,同时把包的大小赋给全局变量uip_len。然后uIP的主控部分调用uip_input()函数,该函数将会根据数据包首部的协议标识处理这个包,并在需要时调用上层应用程序。当uip_input()返回时,一个输出数据包被放在同一个全局缓冲区uip_buf中,其大小赋给uip_len。如果uip_len是0,则说明没有包要发送,否则主控部分调用底层系统的发包函数将数据包发送到网络上[3]。
uIP周期计时用于驱动所有的uIP内部时钟事件。当周期计时激发后,每一个TCP连接都会调用uIP函数uip_periodic()。类似于uip_input()函数,uip_periodic()函数返回时,输出的IP包要放到uip_buf中,供底层系统查询uip_len的大小以决定是否发送。
由于使用TCP/IP的应用很多,因此应用程序作为单独的模块由用户实现。uIP提供一系列接口供用户程序调用,其中大部分接口是作为C的宏命令出现的,之所以这样做主要是考虑到速度、代码大小、效率和堆栈的使用。用户需要把对网络数据包的处理函数作为接口提供给uIP,并将这个函数定义为宏UIP_APPCALL()或者UIP_UDP_APPCALL()。UIP_APPCALL()是用户对TCP数据包的处理,UIP_UDP_APPCALL()是用户对UDP数据包的处理[4]。这样,uIP在接收到底层传来的数据包后,在需要送到上层应用程序处理的地方,直接调用UIP_APPCALL()或者UIP_UDP_APPCALL()即可,无需修改uIP。
2 uIP的UDP协议分析
2.1 UDP协议的实现
当uIP接收到一个UDP数据包后,首先从包头中取出数据的长度,然后重新对包进行校验,如果校验和不对,则直接丢掉这个包。如果校验无误,则对收到的包进行解复用。此时进行如下判断:
if(uip_udp_conn->lport != 0 &&
UDPBUF->destport == uip_udp_conn->lport &&
(uip_udp_conn->rport == 0 ||
UDPBUF->srcport == uip_udp_conn->rport) &&
(uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) || uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) 上述代码中用到的主要变量、数据结构和函数的含义是:
uip_udp_conn->lport:本地UDP的源端口;
uip_udp_conn->rport:本地UDP的目的端口;
UDPBUF->srcport:接收到的数据包中的源端口;
UDPBUF->destport:接收到的数据包中的目的端口;
uip_udp_conn->ripaddr:本地UDP的目的IP地址;
BUF->srcipaddr:接收到的数据包中的源IP地址;
all_zeroes_addr:IP地址0.0.0.0;
all_ones_addr:IP地址255.255.255.255;
uip_ipaddr_cmp:IP地址比较函数,如果参加比较的两个IP地址相等,则返回1。
在uIP的实现中,如果以上判断语句为真,则对接收到的数据包进行处理,处理过程包括调用用户上层处理程序UIP_UDP_APPCALL()、构造新包的包头、计算新包的校验和等,然后将构造好的返回UDP包送到IP层进行处理。 |