uIP是模块化设计的,头文件主要有uip.h、uipopt.h、uip_arp.h、uip_arch.h,核心文件主要包括uip_arp.c、uip.c、uip_arch.c等。另外在源码中给出了几个应用示例,实现了一个简单的http服务器,并且带有部分cgi功能。下面主要结合TCP/IP协议说明各核心文件实现的功能,对代码进行分析。
(1)ARP协议的实现及uIP提供的相关函数。
ARP协议本质是完成网络地址到物理地址的映射。物理地址本例中指以太网类型地址(MAC地址),网络地址特指IP地址。
ARP的以太网封装格式和报文格式如下图所示。
uIP使用一结构体arp_hdr来表示ARP数据帧。注意arp_hdr数据结构中还包括了以太网的头部,硬件类型和协议类型等,真正的ARP数据帧是从u8_thwlen开始的。
ethhdr以太网头部。定义的结构体原型如下:
·dest,SRC:以太网目的地址和源地址,都是6字节,为FFFFFFFFFFFF时是广播地址,以太网上的所有节点都可以收到。
·type:以太网头部的类型一般有两种,如果type=0x0806,表明以太网封装的数据部分为ARP数据包,如果type=0x0800,表明以太网封装的数据部分为IP数据包。
·hwtype:硬件类型字段。指明了发送方想知道的硬件地址的类型,以太网的值为1。
·protocol:协议类型字段。表明要映射的协议地址类型,IP为0X0800。
·hwlen:硬件地址长度。指明了硬件地址和高层协议地址的长度。对于以太网上IP地址请求来讲,值为6。
·protolen:协议地址长度。指明了硬件地址和高层协议地址的长度,对于以太网上的IP地址来讲,值为4。
·opcode:操作字段,用来表示这个报文的类型,ARP请求为l,ARP响应为2,RARP请求为3,RARP响应为4。
·shwaddr:发送端的以太网地址(MAC地址),6字节。
·SIPaddr[2]:发送端的协议地址(IP地址),4字节。
·dhwaddr:接收端的以太网地址(MAC地址),6字节。
·DIPaddr[2]:接收端的协议地址(IP地址),4字节。
uIP协议栈中与ARP协议有关的文件有uip_arp.c。文件中主要包含与arp实现相关的数据结构和相关函数等。
uIP协议栈将IP地址和MAC地址的对应关系保存在一个表arp_table[]中。
statICstructarp_entryxdataarp_table[UIP_ARPTAB_SIZE];表中的每一个元素笔者称之为表项,每一个表项保存的是一个IP地址和MAC地址的对应关系,另外还有一个标志时间的8位变量。显然表中每一个元素都是arp_entry型,arp_entry的定义如下:
下表给出了一个arp_table[]的表格示例
uip_arp.c又件中主要函数说明如下。
①voiduip_arp_init(void)。函数的作用是初始化arp_table,使其中的IP地址全部为0。
②voiduip_arp_timer(void)。这个函数应该每隔一段时间被调用一次,函数的作用是每调用一次,arp_table中的所有元素的老化时间增加1,然后与最大老化时间UIP-ARP_MAXAGE比较,如果大于这个数值,说明这个arptabl表项太老,于是表项被清0,以用来存放更新的数据。
③staticvoiduip_arp_update(u16_t*ipaddr,structuip_eth_addr*ethaddr)。函数是只被uip_arp.c文件中的其他函数调用,作用是更新arp_table中的表项。
首先寻找未使用的表项,若找到则将新的arp对应关系加入其中;若未找到,则寻找arp_table中最老的表项,并用新的数据代替。
④voiduip_arp_iPIN(void)。函数功能是对收到的IP包进行ARP部分的处理。如果收到的IP包中的lP地址在arp_table中存在,则其中相应表项中的MAC地址将会被收到IP包的MAC地址代替。如果arp_table中不存在这个IP地址,则创建一个新的表项。实际上这个函数对收到IP包中的IP地址进行判断是否是本地网络中后,直接又调用uip_arp_update()函数更新arp_table表项。
⑤voiduip_arp_arpin(void)。函数的功能是对收到的ARP数据包进行处理。当收到一个ARP数据包时,应该调用这个函数处理。如果收到的ARP数据包是一个ARP请求的应答,则在这个函数将更新ARP表。如果收到的ARP包是其他主机发送的请求本机MAC地址的数据包,则这个函数生成一个ARP应答包,且生成的数据包存放在uip_buf[]缓冲中。
当函数返回时,全局变量uip_len的值表明网络驱动是否应该发送一个数据包。如果uip_ler]
不为0,则值就是uip_buf[]中存储的要发送的数据包的长度,数据包就存放在uip_buf[]中。
⑥voiduip_arp_out(void)。uip_arp_out()函数的作用是对要发送的IP数据包进行预先处理,根据处理的情况决定是否发送一个ARP请求包以得到IP包中对应IP地址主机的MAC地址。如果要发送的数据包的IP地址是在本地网络中(具有相同的子网掩码),则搜索arp_table寻找是否存在相应的表项,如果存在,则为要发送的IP数据包添加上以太网帧头,然后函数返回。
如果ARP表项中不存在相应的表项,则生成一个ARP请求包,以得到要发送IP包目的IP地址的MAC地址。新生成的ARP包存放在uip_buf[]中代替原有的数据。IP包的重发依靠上层协议(如TCP协议)来完成。当函数返回时,全局变量uip_len的值表明网络驱动是否应该发送一个数据包。如果uip_len不为O,则值就是uipbuf口中存储的要发送的数据包的长度,数据包就存放在Iup_buf[]中。
(2)IP和TCP协议简单说明及uIP中相关接口函数的实现。
IP协议是TCP/IP协议族中最为核心的协议。所有的TCP、UDP数据等都是以口数据包格式传输。IP负责将数据传输到正确的目的地,同时也负责路由。lP数据的传输具有以下特点。
传输数据不能保证到达目的地。数据传输的可靠性由上层协议来提供(如TCP协议)。
IP协议传输的数据是无连接的。
TCP协议用于在不可靠的网络上提供可靠、端到端的数据流通信协议。当传输受到干扰或网络故障等原因使传输的数据不可靠时,就需要其他协议来保证数据传输的完整性与可靠性。TCP协议正是完成这种功能。TCP采用“带重传的肯定确认”和“滑动窗口”来实现数据传输的可靠性和流量控制。具体详细过程请读者参考相关资料。
TCP协议是面向连接的数据传输协议。双方通信之前,先建立连接,然后发送数据,发 送完数据之后,关闭连接。通信的双方建立连接之后,数据沿着这个连接双向传送数据,连接的双方通过序列号和确认号来对数据保持跟踪。
序列号说明当前数据块在数据流中的位置。如果第一个数据块的序列号是0,并且有10字节长,那么下一个数据块的序列号应该是10。
确认号表示接受数据的总数。如果初始的序列号是0,并且收到10字节需要确认,则应答中的确认号就是10。因为TCP的数据传输是双向的,每一方对它自己的传输都保留一个序列号和确认号,并且每一方都对从对方节点接收来的序列号和确认号进行跟踪
TCP的操作可以使用一个具有11种状态的有限状态机来表示。
各状态的描述如下表所示。
本文关键字:暂无联系方式源码-程序,单片机-工控设备 - 源码-程序
上一篇:uIP在51单片机上的移植