lwip源码分析 之 DHCP协议 (二)

一,定时器1

继续上一章,dhcp客户端运行两个定时器,分别周期为1分钟的 void dhcp_coarse_tmr(void); 和 每周期为500ms的 void dhcp_fine_tmr(void);

先看dhcp_fine_tmr()定时任务

//处理dhcp请求超时
void
dhcp_fine_tmr()
{
    
    
  struct netif *netif = netif_list;
  //遍历所有网口
  while (netif != NULL) {
    
    
    if (netif->dhcp != NULL) {
    
        
      //request_timeout -1,表示过去500ms
      if (netif->dhcp->request_timeout > 1) {
    
    
        netif->dhcp->request_timeout--;
      }
      else if (netif->dhcp->request_timeout == 1) {
    
     //请求时间超时
        netif->dhcp->request_timeout--;	//此时timeout=0;
        dhcp_timeout(netif);  //执行超时处理
      }
    }
    netif = netif->next;  //检查下一个网口
  }
}

当dhcp广播请求报文后就进入requesting状态,并设置request_timeout时间。在dhcp_fine_tmr()中,判断是否超时。dhcp_timeout()是超时处理函数:

static void
dhcp_timeout(struct netif *netif)
{
    
    
  struct dhcp *dhcp = netif->dhcp;
  
  //DHCP_BACKING_OFF和DHCP_SELECTING下超时是因为服务器们无响应,可能是广播的发现报文失踪了
  if ((dhcp->state == DHCP_BACKING_OFF) || (dhcp->state == DHCP_SELECTING)) {
    
    
    LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n"));
    dhcp_discover(netif); //重新广播发现报文

  //dhcp处于DHCP_REQUESTING状态而超时,可能是服务器的ack报文丢失
  } else if (dhcp->state == DHCP_REQUESTING) {
    
      
    if (dhcp->tries <= 5) {
    
    
      //重新与该服务器联系,让她重新ack
      dhcp_select(netif);
    } else {
    
    
      //该服务器可能挂了,我们重新广播发现报文,选择别的服务器
      dhcp_release(netif);  //清除之前的ip
      dhcp_discover(netif);
    }
  }

  //DHCP_RENEWING下,可能是再续约报文丢失
  else if (dhcp->state == DHCP_RENEWING) {
    
    
    dhcp_renew(netif);  //重新发送续约报文

  } else if (dhcp->state == DHCP_REBINDING) {
    
     //重新绑定状态下,可能是报文丢失或服务器挂了
    //超过8次无ack,就重新广播,选择其他服务器
    if (dhcp->tries <= 8) {
    
    
      dhcp_rebind(netif);
    } else {
    
    
      dhcp_release(netif);  //释放资源
      dhcp_discover(netif); //重新广播
    }
  } else if (dhcp->state == DHCP_REBOOTING) {
    
    
    if (dhcp->tries < REBOOT_TRIES) {
    
    
      dhcp_reboot(netif);
    } else {
    
    
      dhcp_discover(netif);
    }
  }
}

在超时处理函数中,超时的原因可能是报文丢失或服务器关闭等。所以针对超时的处理有报文重发和重新广播两种方式。

二 定时器2

通过dhcp协议获取的ip地址是有使用时间的。当过了租用时间的一半时,客户端要发送续约报文给服务器,通知服务器是否继续使用该ip地址;

client发送Rebind报文给任何可以用的服务器(Rebind报文中没有server id选项),以延长分配给client的地址的生存时间并且更新其它配置参数,这个消息是在发送Renew消息没有回应后才发送。

dhcp_coarse_tmr()定时器以一分钟的周期执行,检查续约时间和rebind时间是否超时,若超时则分别执行 dhcp_renew(netif); 和 dhcp_rebind(netif); 函数。

void
dhcp_coarse_tmr()
{
    
    
  struct netif *netif = netif_list;
  //遍历网口,检查t1,t2是否超时
  while (netif != NULL) {
    
    
    if (netif->dhcp != NULL) {
    
    
      if (netif->dhcp->t2_timeout-- == 1) {
    
    
        dhcp_t2_timeout(netif);	//rebind超时
      } else if (netif->dhcp->t1_timeout-- == 1) {
    
    
        dhcp_t1_timeout(netif);	//续约超时
      }
    }
    netif = netif->next;
  }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44821644/article/details/114077628