zoukankan      html  css  js  c++  java
  • uip源码剖析【一】——【网络层】ARP解读

    ===================转载请保留头部====================

    作者:souroot   来源:WEB DNA

    连接: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 void
    uip_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)

  • 相关阅读:
    C#对HTTP数据还原
    Nancy.Host的Web应用
    Deep Learning
    业务规则引擎扩展模块
    LB 负载均衡的层次结构(转)
    主要的核心思想是取cookie然后发查询请求,不需要浏览器做代理(转)
    关于java mail 发邮件的问题总结(转)
    使用ping钥匙临时开启SSH:22端口,实现远程安全SSH登录管理就这么简单(转)
    利用Javamail接收QQ邮箱和Gmail邮箱(转)
    android ListView隐藏FooterView(headerView)
  • 原文地址:https://www.cnblogs.com/souroot/p/3033856.html
Copyright © 2011-2022 走看看