打印

LwIP的DHCP功能求教

[复制链接]
11228|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 can123dao 于 2013-7-30 20:43 编辑

已经实现开发板同时或分别做client server,想加上dhcp,由路由自动给开发板分配IP.
#define LWIP_DHCP 1
#define LWIP_UDP 1
#define LWIP_ARP 1
#define DHCP_DOES_ARP_CHECK 1
在netconfig.c里我用了如下代码
void LwIP_Init( void )
{
  struct ip_addr ipaddr;
  struct ip_addr netmask;
  struct ip_addr gw;


   lwip_init();        
            
#if LWIP_DHCP                                                           
  ipaddr.addr = 0;
  netmask.addr = 0;
  gw.addr = 0;

#else                                                                                
  IP4_ADDR(&ipaddr, 192, 168, 0, 16);         
  IP4_ADDR(&netmask, 255, 255, 255, 0);        
  IP4_ADDR(&gw, 192, 168, 0, 1);                        
#endif

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

  netif_set_default(&enc28j60);

  netif_set_up(&enc28j60);

  
#if LWIP_DHCP
  dhcp_start(&enc28j60);
#endif
}
这是网上两个版本的一个,也是STM32 LWIP DEMO里的方法。可是不成功,另一个版本也试了,不成功。抓包结果如下

始终收不ARP_Request:who -has 192.168.0.6 tell 192.168.0.1的ARP_Reply.
dhcp的过程是这样的如果是一个新的client, client 会先发一个dhcp discover, server 收到后会回一个 dhcp offer,这个offer 是broadcast,因为这时client 还没有ip, client 收到 这个offer 后会发一个dhcp request, 然后server 给一个 dhcp ack
这里,就只能看到server给的offer,client却不再给server request.所以不成功。那该如何解决呢。
在dhcp_start()里面有调用dhcp_recv的代码,可是在程序执行过程中,并没有去执行dhcp_recv。有人做过么,求指导。
沙发
hkcj| | 2013-7-30 18:53 | 只看该作者
不是很了解  楼主  帮你顶一个   看看别人的意见

使用特权

评论回复
板凳
can123dao|  楼主 | 2013-7-30 20:15 | 只看该作者
hkcj 发表于 2013-7-30 18:53
不是很了解  楼主  帮你顶一个   看看别人的意见

TKS

使用特权

评论回复
地板
can123dao|  楼主 | 2013-7-31 16:29 | 只看该作者
自己来顶。这个原因似乎是因为CLIENT的网卡收不到ARP包,可是在ENC28J60的初始化里加上了滤入广播包时,还是接收不到数据,这是什么原因呢,待解决。enc28j60Read(EPKTCNT) == 0,问题,继续

使用特权

评论回复
5
icicicici| | 2013-10-10 11:43 | 只看该作者
最近也在研究这个,我的程序加上#define LWIP_DHCP  1时,告诉我说 error:  #20: identifier "netif" is undefined,不知道楼主有遇到没?

使用特权

评论回复
6
can123dao|  楼主 | 2013-10-10 21:22 | 只看该作者
icicicici 发表于 2013-10-10 11:43
最近也在研究这个,我的程序加上#define LWIP_DHCP  1时,告诉我说 error:  #20: identifier "netif" is un ...

使用特权

评论回复
7
xiaosi204| | 2014-3-21 16:28 | 只看该作者
不知道你的问题现在解决了没有,能不能分享一下?我的邮箱ye_zi204@163.com

我用电脑端做服务器,用网络抓包查看会一段时间发一个这样的信息出来
类型           长度           源IP                  源端口               源MAC                                                 目的IP                    目的端口              目的MAC
UDP           350                                      67          04:02:35:00:00:01(开发板代码设定的)            255:255:255:255         68                  FF: FF: FF: FF: FF: FF

要是电脑IP没有和开发板设对应的话,抓包软件就会有这样的信息ARP-Request:who has 192:168:1:103 tell 0:0:0:0

现在运行之后一直都分配不到IP不知道是怎么回事?

我用一个小路由器就接开发板和电脑网口

使用特权

评论回复
8
湖北泽翔| | 2014-4-11 20:59 | 只看该作者
我也正在学习

使用特权

评论回复
9
can123dao|  楼主 | 2014-4-13 22:07 | 只看该作者
本帖最后由 can123dao 于 2014-4-13 22:09 编辑
xiaosi204 发表于 2014-3-21 16:28
不知道你的问题现在解决了没有,能不能分享一下?我的邮箱

我用电脑端做服务器,用网络抓包查看会一段时间 ...

我好久没搞这个了 被迫换了个方向,当时自己留的点说明你看有用没。
在使用DHCP功能时遇到问题两个:1、DHCP交互过程,无法接收到DHCP客户端给出的OFFER包。原因,网卡初始化的问题。由于测试DHCP的程序是在其它基础程序上改进过来的,最初的网卡初始化并没有打开“滤入广播包”的功能。解决方法(for enc28j60):将ERXFCON寄存器的BCEN位置1,enc28j60Write(ERXFCON, ERXFCON_BCEN);
                              2、IP分配成功后,做为CLIENT的MCU无法自动连到PC端的SERVER上,tcp_connect不调用回调函数connected。原因,程序最初是使用的静态IP,所以一开始网卡的MAC就和IP初始化对应好了,故可以自动连接。而使用DHCP时,DHCP有一个过程,需要一定的时间,即在IP分配不成功时去连接肯定是不成功的。DHCP中定义了七种状态,分别为INIT状态,SELECTING状态,REQUESTING状态,BOUND状态,RENEWING状态,REBINDING状态,REBOOT状态。只有等待DHCP状态为BOUN( 用户收到SERVER的确认报文后,将分配的IP地址与网卡绑定,开始使用该IP地址。)时才能进行连接。解决方法:
                while(1){
                        LwIP_Periodic_Handle(LocalTime);
                        if(enc28j60.dhcp->state == DHCP_BOUND && init_flag == 0){//或者放出来用单独用while(enc28j60.dhcp->state == DHCP_BOUND && init_flag == 0),未测试
                                if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == RESET){
                                        tcp_client_init();
                                        init_flag =1;//全局变量,保证初始化完成后不重复初始化
                                }
                        }
                }

关于阻塞和非阻塞的理解
简单点说:

阻塞就是干不完不准回来,   
非阻塞就是你先干,我现看看有其他事没有,完了告诉我一声

我们拿最常用的send和recv两个函数来说吧...
比如你调用send函数发送一定的Byte,在系统内部send做的工作其实只是把数据传输(Copy)到TCP/IP协议栈的输出缓冲区,它执行成功并不代表数据已经成功的发送出去了,如果TCP/IP协议栈没有足够的可用缓冲区来保存你Copy过来的数据的话...这时候就体现出阻塞和非阻塞的不同之处了:对于阻塞模式的socket send函数将不返回直到系统缓冲区有足够的空间把你要发送的数据Copy过去以后才返回,而对于非阻塞的socket来说send会立即返回WSAEWOULDDBLOCK告诉调用者说:"发送操作被阻塞了!!!你想办法处理吧..."
对于recv函数,同样道理,该函数的内部工作机制其实是在等待TCP/IP协议栈的接收缓冲区通知它说:嗨,你的数据来了.对于阻塞模式的socket来说如果TCP/IP协议栈的接收缓冲区没有通知一个结果给它它就一直不返回:耗费着系统资源....对于非阻塞模式的socket该函数会马上返回,然后告诉你:WSAEWOULDDBLOCK---"现在没有数据,回头在来看看"

void LwIP_Init( void )
{
  struct ip_addr ipaddr;
  struct ip_addr netmask;
  struct ip_addr gw;

   /*调用LWIP初始化函数,
   初始化网络接口结构体链表、内存池、pbuf结构体,启动协议栈管理进程*/
   lwip_init();       
          
#if LWIP_DHCP                                                                   //若使用DHCP协议
  ipaddr.addr = 0;
  netmask.addr = 0;
  gw.addr = 0;
#else                                                                                //
  IP4_ADDR(&ipaddr, 192, 168, 0, 16);                  //设置网络接口的ip地址
  IP4_ADDR(&netmask, 255, 255, 255, 0);                //子网掩码
  IP4_ADDR(&gw, 192, 168, 0, 1);                        //网关

#endif

  /*初始化enc28j60与LWIP的接口,参数为网络接口结构体、ip地址、
  子网掩码、网关、网卡信息指针、初始化函数、输入函数*/
  netif_add(&enc28j60, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &ethernet_input);

  /*把enc28j60设置为默认网卡 .*/
  netif_set_default(&enc28j60);

  /*  When the netif is fully configured this function must be called.*/
  netif_set_up(&enc28j60); //使能enc28j60接口

#if LWIP_DHCP                                   //若使用了DHCP
  dhcp_start(&enc28j60);           //启动DHCP
#endif

}

使用特权

评论回复
评分
参与人数 2威望 +3 收起 理由
名不虚传 + 1 很给力! 这个是对的,我之前看到一个要在dh.
xiaosi204 + 2 很给力!
10
icecut| | 2014-4-14 09:32 | 只看该作者
我也顶一下,暂时没研究

使用特权

评论回复
11
名不虚传| | 2015-3-30 18:31 | 只看该作者
这个设置是对的,我之前看过一个要在dhcp_start()后面把获得的IP再写进网口的,两个我都实验了,只有这个是对的!

使用特权

评论回复
12
永恒heng| | 2015-4-7 13:27 | 只看该作者
mark……第一次连接没问题,分配上了,可是后来不行了,说明那里还没有修改好,再找找看~

使用特权

评论回复
13
永恒heng| | 2015-4-7 13:42 | 只看该作者
我想问一下 if(enc28j60.dhcp->state == DHCP_BOUND && init_flag == 0)这句中的enc28j60是什么类型的?

使用特权

评论回复
14
can123dao|  楼主 | 2015-4-9 15:32 | 只看该作者
永恒heng 发表于 2015-4-7 13:42
我想问一下 if(enc28j60.dhcp->state == DHCP_BOUND && init_flag == 0)这句中的enc28j60是什么类型的? ...

struct netif enc28j60;

使用特权

评论回复
15
duxinlng| | 2015-11-11 17:30 | 只看该作者
搞定没有,有的路由器可以成功,有的不行,为什么啊?

使用特权

评论回复
16
can123dao|  楼主 | 2015-12-3 22:46 | 只看该作者
能说的差不多都在这个帖子了,过去太久远了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

114

帖子

2

粉丝