===================转载请保留头部====================
作者:souroot 来源:
连接:http://www.cnblogs.com/souroot/archive/2013/04/21/3033856.html
关键词:TCPIP UIP 51单片机 计算机网络 网络工程专业 手把手教你写tcpip协议栈
版权: Q college 版权所有
=====================以下为正文=====================
uip对TCPIP协议栈做了最大的精简,最最基本的TCPIP协议栈,最起码要有4个协议:ARP、IP、ICMP、TCP,
为什么ARP很重要呢?因为报文在网络上传递,最终还是需要二层地址,即MAC地址的,而运行uip的主机只知道报文的目的ip地址,而对MAC地址是不了解的。
这时候就需要ARP了。
====ARP流程=====
ARP是已知对端的IP地址,想要获取对端的MAC地址,就会发送一个ARP请求,对端收到ARP请求后,会发送一个ARP应答给源主机。这是个大概的流程。下面讲一下详细的流程:
====详细流程=====
【ARP请求的发送】
主机首先检查要发送的报文的目的IP是否和自己在同一网段,如果在同一网段,就请求目的主机的MAC地址;如果不是同一网段的,就请求网关的MAC地址。
【接收到ARP请求】
如果设备收到个ARP请求,发现请求的就是自己的MAC,首先把对方的IP和MAC映射放到自己的ARP表项中,然后填好ARP应答后,单播给发送ARP请求的
设备。
【接收到ARP应答】
这个很简单了,收到了ARP应答就把对方的IP和MAC地址映射表存入自己的ARP表项即可
====ARP帧格式====
下面讲一下ARP的帧格式:
ARP帧由14字节的以太网首部和28字节的ARP头组成。
----以太网头部解释----
这个比较简单,就是目的MAC,源MAC,以及以太帧中封装的三层报文类型,如果是ip报文,就是0x0800, ARP报文的话,就是0x0806
----ARP头部解释----
硬件类型:以太网地址用1表示;
协议类型:字段表示要映射的协议地址类型它的值为 0 x 0 8 0 0即表示I P地址;
下面两个字节是硬件地址长度和协议地址长度,分别为6字节和4字节;
OP为操作类型,1表示ARP请求,2表示ARP应答;
对于ARP请求来说,除了目的以太网地址,其他的信息都要填充(因为ARP请求就是要获取目的MAC地址)。当目的端收到ARP请求后,目的端把自己的MAC地址填入此报文中,然后把发送地址换成自己的地址(包括MAC和IP),并把OP位置为2(即表示ARP应答),然后发送出去。
====uip中ARP报文的结构体====
uip中的arp基本都放在uip_arp.h和uip_arp.c中
主要包含以下函数接口:
/*-----------------------------------------------------------------------------------*/
/** * Periodic ARP processing function. * * This function performs periodic timer processing in the ARP module * and should be called at regular intervals. The recommended interval * is 10 seconds between the calls. * 每10s就需要被main函数调用一次,在ARP老化后把表项清零 *//*-----------------------------------------------------------------------------------*/void uip_arp_timer(void);
/* 收到ip报文或者ARP报文就可能调用此函数,更新ARP表项*/
static voiduip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
/*-----------------------------------------------------------------------------------*/
/** * ARP processing for incoming IP packets * * This function should be called by the device driver when an IP * packet has been received. The function will check if the address is * in the ARP cache, and if so the ARP cache entry will be * refreshed. If no ARP cache entry was found, a new one is created. * * This function expects an IP packet with a prepended Ethernet header * in the uip_buf[] buffer, and the length of the packet in the global * variable uip_len. * * 收到IP报文也需要更新ARP表项 *//*-----------------------------------------------------------------------------------*/void uip_arp_ipin(void)
/*-----------------------------------------------------------------------------------*/
/** * ARP processing for incoming ARP packets. * * This function should be called by the device driver when an ARP * packet has been received. The function will act differently * depending on the ARP packet type: if it is a reply for a request * that we previously sent out, the ARP cache will be filled in with * the values from the ARP reply. If the incoming ARP packet is an ARP * request for our IP address, an ARP reply packet is created and put * into the uip_buf[] buffer. * * When the function returns, the value of the global variable uip_len * indicates whether the device driver should send out a packet or * not. If uip_len is zero, no packet should be sent. If uip_len is * non-zero, it contains the length of the outbound packet that is * present in the uip_buf[] buffer. * * This function expects an ARP packet with a prepended Ethernet * header in the uip_buf[] buffer, and the length of the packet in the * global variable uip_len. * * 收到ARP报文,不管是请求报文还是应答报文,做出相应的处理 *//*-----------------------------------------------------------------------------------*/void uip_arp_arpin(void)
/*-----------------------------------------------------------------------------------*/
/** * Prepend Ethernet header to an outbound IP packet and see if we need * to send out an ARP request. * * This function should be called before sending out an IP packet. The * function checks the destination IP address of the IP packet to see * what Ethernet MAC address that should be used as a destination MAC * address on the Ethernet. * * If the destination IP address is in the local network (determined * by logical ANDing of netmask and our IP address), the function * checks the ARP cache to see if an entry for the destination IP * address is found. If so, an Ethernet header is prepended and the * function returns. If no ARP cache entry is found for the * destination IP address, the packet in the uip_buf[] is replaced by * an ARP request packet for the IP address. The IP packet is dropped * and it is assumed that they higher level protocols (e.g., TCP) * eventually will retransmit the dropped packet. * * If the destination IP address is not on the local network, the IP * address of the default router is used instead. * * When the function returns, a packet is present in the uip_buf[] * buffer, and the length of the packet is in the global variable * uip_len. * * 主动发送ARP请求 *//*-----------------------------------------------------------------------------------*/void uip_arp_out(void)