1. 程式人生 > >stm32 lwip的DHCP

stm32 lwip的DHCP

stm32f107 lwip dhcp
第一篇        DHCP自動獲取功能的實現
概要
  DHCP在電腦中經常用到,因為我們並不關心我們電腦的IP是多少 只要能連上網路就行了。在嵌入式的產品裝置中,DHCP用到的比較少,因為很多的操作是通過ip來進行的。除非那種有伺服器的系統裝置會用到。這裡我們只能簡單說一下流程,設計的程式碼太多了,具體的需要學習者自己去慢慢研究。
dhcp模組:
dhcp模組用於獲取裝置ip地址的相關資訊。其處理入口主要有這麼幾個dpch的啟動、dpch的接收報文處理以及定時器模組的處理。
主要的介面原型如下:
err_t dhcp_start(struct netif *netif)

該介面用於裝置啟動dhcp模組,主要是客戶端的功能。該模組實現裝置dhcp描述結構生成,並將dhcp的埠繫結到udp協議中,以及將本dhcp模組跟遠端伺服器埠進行繫結。最後啟動dhcp申請。
static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
該介面為一個註冊介面,用於dhcp報文接收。在start dhcp時,該介面通過dhcp的udp pcb註冊到udp協議層。Udp進行報文處理後,根據埠呼叫該註冊介面。該介面中,實現dhcp報文的協議處理。

Void dhcp_fine_tmr()
Void dhcp_coarse_tmr()
這兩個函式介面實現了dhcp的相關超時處理監控。上面一個用於請求應答超時處理。下面一個用於地址租用情況的到期處理。
從原始碼分析看,上述的介面在應用lwip的協議棧時,需要重點關注。對於小記憶體應用的場合,該協議棧的記憶體管理以及pbuf應用部分需要自行改寫。
開啟工程《科星F107開發板網路應用篇之DHCP自動獲取功能》
  進入主函式
int main(void)
{
  System_Setup();
  LwIP_Init();
  while (1)
  {    
        /* Periodic tasks */
        System_Periodic_Handle();


  }
}
   主要看一下 DHCP和靜態的時候配置有哪些不同
      進入函式LwIP_Init();
     void LwIP_Init(void)
{
  struct ip_addr ipaddr;
  struct ip_addr netmask;
  struct ip_addr gw;

uint8_t macaddress[6]={0,0,0,0,0,1};
    mem_init();
    memp_init();
ipaddr.addr = 0;
    netmask.addr = 0;
    gw.addr = 0;
  IP 閘道器 子網掩碼 我們設定為0,就是沒有值。需要我們自動獲取到。

  Set_MAC_Address(macaddress);設定MAC地址,這個不管任何時候都要設定。


//建立一個網路介面

  netif_add(&netif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);

  netif_set_default(&netif);

  dhcp_start(&netif);主要是這句,這一句就開始了自動獲取的程序,以2,4,8,16秒為間隔,加上1-1000毫秒之間隨機長度的時間 

  netif_set_up(&netif);

}
DHCP獲取IP的簡單過程
  當DHCP客戶機第一次登入網路的時候(也就是客戶機上沒有任何IP地址資料時),它會通過UDP 67埠向網路上發出一個DHCPDISCOVER資料包(包中包含客戶機的MAC地址和計算機名等資訊)。因為客戶機還不知道自己屬於哪一個網路,所以封包的源地址為0.0.0.0,目標地址為255.255.255.255,然後再附上DHCP discover的資訊,向網路進行廣播。
DHCP discover的等待時間預設為1秒,也就是當客戶機將第一個DHCP discover封包送出去之後,在1秒之內沒有得到迴應的話,就會進行第二次DHCP discover廣播。若一直沒有得到迴應,客戶機會將這一廣播包重新發送四次(以2,4,8,16秒為間隔,加上1-1000毫秒之間隨機長度的時間)。
執行完dhcp_start(&netif);這個函式,開發板就開始和所接的路由器獲取IP的程序。
那麼我們程式怎麼知道是否獲取到了沒有呢 接著看函式
System_Periodic_Handle();
進入
void System_Periodic_Handle(void)
{
  GET_DHCP_IP(LocalTime);
   LwIP_Periodic_Handle(LocalTime);
}
進入函式GET_DHCP_IP(LocalTime);
void GET_DHCP_IP(__IO uint32_t localtime)


  struct ip_addr ipaddr;
  struct ip_addr netmask;
  struct ip_addr gw;

  /* 250 ms */
  if (localtime - DisplayTimer >= GET_DHCP_MSECS) 每250ms檢測一次是否得到IP
  {
    DisplayTimer = localtime;

    /* We have got a new IP address so update the display */
    if (IPaddress != netif.ip_addr.addr)
    {
      __IO uint8_t iptab[4];


      /* Read the new IP address */
     IPaddress = netif.ip_addr.addr;
      iptab[0] = (uint8_t)(IPaddress >> 24);
      iptab[1] = (uint8_t)(IPaddress >> 16);
      iptab[2] = (uint8_t)(IPaddress >> 8);
      iptab[3] = (uint8_t)(IPaddress);
      if (netif.flags & NETIF_FLAG_DHCP)如果得到IP的話 建立埠連線
      {   
            iptab[0] = (uint8_t)(IPaddress >> 24);
        iptab[1] = (uint8_t)(IPaddress >> 16);
        iptab[2] = (uint8_t)(IPaddress >> 8);
        iptab[3] = (uint8_t)(IPaddress);
             server_init();初始化UDP埠,其實到這裡DHCP已經成功了 這裡初始化這個埠 是為了增加UDP掃描,以便我們能知道得到的ip是什麼。這個函式 還有掃描的功能就不在講了 前面剛剛講過。可以自己點進去看一下程式。
}

      }
    else if (IPaddress == 0)
    {
               if (netif.dhcp->tries > MAX_DHCP_TRIES) 如果是超時進入超時處理
      {
        struct ip_addr ipaddr;
        struct ip_addr netmask;
        struct ip_addr gw
        dhcp_stop(&netif);
        IP4_ADDR(&ipaddr, 192, 168, 1, 8);
        IP4_ADDR(&netmask, 255, 255, 255, 0);
        IP4_ADDR(&gw, 192, 168, 1, 1);
      netif_set_addr(&netif, &ipaddr , &netmask, &gw);
    }
  } 
}
上面的函式主要是檢測是不是獲取到IP
再看另一個主函式LwIP_Periodic_Handle(LocalTime);
進入 主要看和DHCP有關的兩個函式
void LwIP_Periodic_Handle(__IO uint32_t localtime)
{

  /* TCP periodic process every 250 ms */
  if (localtime - TCPTimer >= TCP_TMR_INTERVAL)
  {
    TCPTimer =  localtime;
    tcp_tmr();
  }
  /* ARP periodic process every 5s */
  if (localtime - ARPTimer >= ARP_TMR_INTERVAL)
  {
    ARPTimer =  localtime;
    etharp_tmr();
  }

#if LWIP_DHCP
  /* Fine DHCP periodic process every 500ms */
  if (localtime - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS)
  {
    DHCPfineTimer =  localtime;
    dhcp_fine_tmr();請求應答超時處理
  }。

  /* DHCP Coarse periodic process every 60s */
  if (localtime - DHCPcoarseTimer >= DHCP_COARSE_TIMER_MSECS)
  {
    DHCPcoarseTimer =  localtime;
    dhcp_coarse_tmr();地址租用情況的到期處理
  }
#endif

}