下面是部分代码,我用红 {MOD}标记了下 我跟踪后执行的步骤 不知分析的是否对。请用过的人帮看下。一直获取不到IP 总是在检查超时--发DISSEVER包---在返回获取失败
/**
*@brief 发送DISCOVER信息给DHCP服务器
*@param 无
*@return 无
*/
void send_DHCP_DISCOVER(void)
{
uint8 ip[4] = {255,255,255,255};
uint16 i=0;
//the host name modified
uint8 host_name[12];
//*((uint32*)DHCP_SIP)=0;
//*((uint32*)DHCP_REAL_SIP)=0;
memset((void*)pRIPMSG,0,sizeof(RIP_MSG)); /*清空pRIPMSG的 sizeof(RIP_MSG) 个空间*/
pRIPMSG->op = DHCP_BOOTREQUEST;
pRIPMSG->htype = DHCP_HTYPE10MB;
pRIPMSG->hlen = DHCP_HLENETHERNET;
pRIPMSG->hops = DHCP_HOPS;
pRIPMSG->xid = htonl(DHCP_XID);
pRIPMSG->secs = htons(DHCP_SECS);
pRIPMSG->flags =htons(DHCP_FLAGSBROADCAST);
pRIPMSG->chaddr[0] = SRC_MAC_ADDR[0];
pRIPMSG->chaddr[1] = SRC_MAC_ADDR[1];
pRIPMSG->chaddr[2] = SRC_MAC_ADDR[2];
pRIPMSG->chaddr[3] = SRC_MAC_ADDR[3];
pRIPMSG->chaddr[4] = SRC_MAC_ADDR[4];
pRIPMSG->chaddr[5] = SRC_MAC_ADDR[5];
/* MAGIC_COOKIE */
pRIPMSG->OPT[i++] = (uint8)((MAGIC_COOKIE >> 24)& 0xFF);
pRIPMSG->OPT[i++] = (uint8)((MAGIC_COOKIE >> 16)& 0xFF);
pRIPMSG->OPT[i++] = (uint8)((MAGIC_COOKIE >> 8)& 0xFF);
pRIPMSG->OPT[i++] = (uint8)(MAGIC_COOKIE& 0xFF);
/* Option Request Param. */
pRIPMSG->OPT[i++] = dhcpMessageType;
pRIPMSG->OPT[i++] = 0x01;
pRIPMSG->OPT[i++] = DHCP_DISCOVER;
/*Client identifier*/
pRIPMSG->OPT[i++] = dhcpClientIdentifier;
pRIPMSG->OPT[i++] = 0x07;
pRIPMSG->OPT[i++] = 0x01;
pRIPMSG->OPT[i++] = SRC_MAC_ADDR[0];
pRIPMSG->OPT[i++] = SRC_MAC_ADDR[1];
pRIPMSG->OPT[i++] = SRC_MAC_ADDR[2];
pRIPMSG->OPT[i++] = SRC_MAC_ADDR[3];
pRIPMSG->OPT[i++] = SRC_MAC_ADDR[4];
pRIPMSG->OPT[i++] = SRC_MAC_ADDR[5];
// host name
pRIPMSG->OPT[i++] = hostName;
// set the host name
sprintf((char*)host_name,"%.4s-%02X%02X%02X",DEVICE_ID,SRC_MAC_ADDR[3],SRC_MAC_ADDR[4],SRC_MAC_ADDR[5]);
pRIPMSG->OPT[i++] = (uint8)strlen((char*)host_name);
strcpy((char*)(&(pRIPMSG->OPT)),(char*)host_name);
i+=(uint16)strlen((char*)host_name);
pRIPMSG->OPT[i++] = dhcpParamRequest;
pRIPMSG->OPT[i++] = 0x06;
pRIPMSG->OPT[i++] = subnetMask;
pRIPMSG->OPT[i++] = routersOnSubnet;
pRIPMSG->OPT[i++] = dns;
pRIPMSG->OPT[i++] = domainName;
pRIPMSG->OPT[i++] = dhcpT1value;
pRIPMSG->OPT[i++] = dhcpT2value;
pRIPMSG->OPT[i++] = endOption;
/* send broadcasting packet */
//printf("send dhcp discover %s
",EXTERN_DHCPBUF);
//for(uint8 i=0; i<3; i++)
//Delay_ms(800);
sendto(SOCK_DHCP, (uint8 *)pRIPMSG, sizeof(RIP_MSG), ip, DHCP_SERVER_PORT);
#ifdef DHCP_DEBUG
printf("sent DHCP_DISCOVER
");
#endif
}
/**
*@brief 发送释放消息
*@param msgtype:是否为7
*@return 无
*/
void send_DHCP_RELEASE_DECLINE(char msgtype)
{
uint16 i =0;
uint8 ip[4];
memset((void*)pRIPMSG,0,sizeof(RIP_MSG));
pRIPMSG->op = DHCP_BOOTREQUEST;
pRIPMSG->htype = DHCP_HTYPE10MB;
pRIPMSG->hlen = DHCP_HLENETHERNET;
pRIPMSG->hops = DHCP_HOPS;
pRIPMSG->xid = htonl(DHCP_XID);
pRIPMSG->secs = htons(DHCP_SECS);
pRIPMSG->flags =0;// DHCP_FLAGSBROADCAST;
memcpy(pRIPMSG->chaddr,SRC_MAC_ADDR,6);
/* MAGIC_COOKIE */
pRIPMSG->OPT[i++] = (uint8)((MAGIC_COOKIE >> 24) & 0xFF);
pRIPMSG->OPT[i++] = (uint8)((MAGIC_COOKIE >> 16) & 0xFF);
pRIPMSG->OPT[i++] = (uint8)((MAGIC_COOKIE >> 8) & 0xFF);
pRIPMSG->OPT[i++] = (uint8)(MAGIC_COOKIE & 0xFF);
/* Option Request Param. */
pRIPMSG->OPT[i++] = dhcpMessageType;
pRIPMSG->OPT[i++] = 0x01;
pRIPMSG->OPT[i++] = ((!msgtype) ? DHCP_RELEASE : DHCP_DECLINE);
pRIPMSG->OPT[i++] = dhcpClientIdentifier;
pRIPMSG->OPT[i++] = 0x07;
pRIPMSG->OPT[i++] = 0x01;
pRIPMSG->OPT[i++] = SRC_MAC_ADDR[0];
pRIPMSG->OPT[i++] = SRC_MAC_ADDR[1];
pRIPMSG->OPT[i++] = SRC_MAC_ADDR[2];
pRIPMSG->OPT[i++] = SRC_MAC_ADDR[3];
pRIPMSG->OPT[i++] = SRC_MAC_ADDR[4];
pRIPMSG->OPT[i++] = SRC_MAC_ADDR[5];
pRIPMSG->OPT[i++] = dhcpServerIdentifier;
pRIPMSG->OPT[i++] = 0x04;
pRIPMSG->OPT[i++] = DHCP_SIP[0];
pRIPMSG->OPT[i++] = DHCP_SIP[1];
pRIPMSG->OPT[i++] = DHCP_SIP[2];
pRIPMSG->OPT[i++] = DHCP_SIP[3];
if(msgtype)
{
pRIPMSG->OPT[i++] = dhcpRequestedIPaddr;
pRIPMSG->OPT[i++] = 0x04;
pRIPMSG->OPT[i++] = GET_SIP[0];
pRIPMSG->OPT[i++] = GET_SIP[1];
pRIPMSG->OPT[i++] = GET_SIP[2];
pRIPMSG->OPT[i++] = GET_SIP[3];
#ifdef DHCP_DEBUG
printf("sent DHCP_DECLINE
");
#endif
}
#ifdef DHCP_DEBUG
else
{
printf("sent DHCP_RELEASE
");
}
#endif
pRIPMSG->OPT[i++] = endOption;
if(msgtype) memset(ip,0xFF,4);
else
memcpy(ip,DHCP_SIP,4);
//printf("send dhcp decline
");
sendto(SOCK_DHCP, (uint8 *)pRIPMSG, sizeof(RIP_MSG), ip, DHCP_SERVER_PORT);
}
/**
*@brief 解析获得的DHCP消息
*@param length:解析消息长度
*@return 0:解析失败 其他:解析成功
*/
uint8 parseDHCPMSG(uint16 length)
{
uint8 svr_addr[6];
uint16 svr_port;
uint16 len;
uint8 * p;
uint8 * e;
uint8 type;
uint8 opt_len = 0;
len = recvfrom(SOCK_DHCP, (uint8 *)pRIPMSG, length, svr_addr, &svr_port);
#ifdef DHCP_DEBUG
printf("DHCP_SIP:%u.%u.%u.%u
",DHCP_SIP[0],DHCP_SIP[1],DHCP_SIP[2],DHCP_SIP[3]);
printf("DHCP_RIP:%u.%u.%u.%u
",DHCP_REAL_SIP[0],DHCP_REAL_SIP[1],DHCP_REAL_SIP[2],DHCP_REAL_SIP[3]);
printf("svr_addr:%u.%u.%u.%u
",svr_addr[0],svr_addr[1],svr_addr[2],svr_addr[3]);
#endif
if(pRIPMSG->op != DHCP_BOOTREPLY || svr_port != DHCP_SERVER_PORT)
{
#ifdef DHCP_DEBUG
printf("DHCP : NO DHCP MSG
");
#endif
return 0;
}
if(memcmp(pRIPMSG->chaddr,SRC_MAC_ADDR,6) != 0 || pRIPMSG->xid != htonl(DHCP_XID))
{
#ifdef DHCP_DEBUG
printf("No My DHCP Message. This message is ignored.
");
printf(" SRC_MAC_ADDR(%02X.%02X.%02X.",SRC_MAC_ADDR[0],SRC_MAC_ADDR[1],SRC_MAC_ADDR[2]);
printf("%02X.%02X.%02X)",SRC_MAC_ADDR[3],SRC_MAC_ADDR[4],SRC_MAC_ADDR[5]);
printf(", pRIPMSG->chaddr(%02X.%02X.%02X.",(char)pRIPMSG->chaddr[0],(char)pRIPMSG->chaddr[1],(char)pRIPMSG->chaddr[2]);
printf("%02X.%02X.%02X)",pRIPMSG->chaddr[3],pRIPMSG->chaddr[4],pRIPMSG->chaddr[5]);
printf(" pRIPMSG->xid(%08X), DHCP_XID(%08X)",pRIPMSG->xid,(DHCP_XID));
printf(" pRIMPMSG->yiaddr:%d.%d.%d.%d
",pRIPMSG->yiaddr[0],pRIPMSG->yiaddr[1],pRIPMSG->yiaddr[2],pRIPMSG->yiaddr[3]);
#endif
return 0;
}
if( *((uint32*)DHCP_SIP) != 0x00000000 )
{
if( *((uint32*)DHCP_REAL_SIP) != *((uint32*)svr_addr) &&
*((uint32*)DHCP_SIP) != *((uint32*)svr_addr) )
{
#ifdef DHCP_DEBUG
printf("Another DHCP sever send a response message. This is ignored.
");
printf(" IP:%u.%u.%u.%u
",svr_addr[0],svr_addr[1],svr_addr[2],svr_addr[3]);
#endif
return 0;
}
}
memcpy(GET_SIP,pRIPMSG->yiaddr,4);
#ifdef DHCP_DEBUG
printf("DHCP MSG received
");
printf("yiaddr : %u.%u.%u.%u
",GET_SIP[0],GET_SIP[1],GET_SIP[2],GET_SIP[3]);
#endif
type = 0;
p = (uint8 *)(&pRIPMSG->op);
p = p + 240;
e = p + (len - 240);
#ifdef DHCP_DEBUG
printf("p : %08X e : %08X len : %d
", (uint32)p, (uint32)e, len);
#endif
while ( p < e )
{
switch ( *p++ )
{
case endOption :
return type;
case padOption :
break;
case dhcpMessageType :
opt_len = *p++;
type = *p;
#ifdef DHCP_DEBUG
printf("dhcpMessageType : %02X
", type);
#endif
break;
case subnetMask :
opt_len =* p++;
memcpy(GET_SN_MASK,p,4);
#ifdef DHCP_DEBUG
printf("subnetMask : ");
printf("%u.%u.%u.%u
",GET_SN_MASK[0],GET_SN_MASK[1],GET_SN_MASK[2],GET_SN_MASK[3]);
#endif
break;
case routersOnSubnet :
opt_len = *p++;
memcpy(GET_GW_IP,p,4);
#ifdef DHCP_DEBUG
printf("routersOnSubnet : ");
printf("%u.%u.%u.%u
",GET_GW_IP[0],GET_GW_IP[1],GET_GW_IP[2],GET_GW_IP[3]);
#endif
break;
case dns :
opt_len = *p++;
memcpy(GET_DNS_IP,p,4);
break;
case dhcpIPaddrLeaseTime :
opt_len = *p++;
dhcp_lease_time = ntohl(*((uint32*)p));
#ifdef DHCP_DEBUG
printf("dhcpIPaddrLeaseTime : %d
", dhcp_lease_time);
#endif
break;
case dhcpServerIdentifier :
opt_len = *p++;
#ifdef DHCP_DEBUG
printf("DHCP_SIP : %u.%u.%u.%u
", DHCP_SIP[0], DHCP_SIP[1], DHCP_SIP[2], DHCP_SIP[3]);
#endif
if( *((uint32*)DHCP_SIP) == 0 ||
*((uint32*)DHCP_REAL_SIP) == *((uint32*)svr_addr) ||
*((uint32*)DHCP_SIP) == *((uint32*)svr_addr) )
{
memcpy(DHCP_SIP,p,4);
memcpy(DHCP_REAL_SIP,svr_addr,4); // Copy the real ip address of my DHCP server
#ifdef DHCP_DEBUG
printf("My dhcpServerIdentifier : ");
printf("%u.%u.%u.%u
", DHCP_SIP[0], DHCP_SIP[1], DHCP_SIP[2], DHCP_SIP[3]);
printf("My DHCP server real IP address : ");
printf("%u.%u.%u.%u
", DHCP_REAL_SIP[0], DHCP_REAL_SIP[1], DHCP_REAL_SIP[2], DHCP_REAL_SIP[3]);
#endif
}
else
{
#ifdef DHCP_DEBUG
printf("Another dhcpServerIdentifier :
");
printf(" MY(%u.%u.%u.%u) ", DHCP_SIP[0], DHCP_SIP[1], DHCP_SIP[2], DHCP_SIP[3]);
printf("Another(%u.%u.%u.%u)
", svr_addr[0], svr_addr[1], svr_addr[2], svr_addr[3]);
#endif
}
break;
default :
opt_len = *p++;
#ifdef DHCP_DEBUG
printf("opt_len : %u
", opt_len);
#endif
break;
} // switch
p+=opt_len;
} // while
return 0;
}
/**
*@brief 检查DHCP状态
*@param s: socket数
*@return 返回得到的DHCP状态
DHCP_RET_NONE: 未获取到IP地址
DHCP_RET_TIMEOUT:超时
DHCP_RET_UPDATE: 获取成功
DHCP_RET_CONFLICT:IP地址冲突
*/
uint8 check_DHCP_state(SOCKET s)
{
uint16 len; /*定义一个表示接收数据大小变量*/
uint8 type; /*定义一个表示接收封包类型变量*/
type = 0;
if(getSn_SR(s)!=SOCK_CLOSED) /*socket处于打开状态*/
{
if ((len = getSn_RX_RSR(s)) > 0) /*接收到数据*/
{
printf("len = %d
",len);
type = parseDHCPMSG(len); /*解析收到的封包类型*/
printf("analysis type =%d
",type);
}
}
else /*socket处于关闭状态,重新初始化socket*/
{
printf("socket close
");
if(dhcp_state == STATE_DHCP_READY)
{
printf("dhcp client strus
");
第三步 init_dhcp_client();
#ifdef DHCP_DEBUG
printf("state : STATE_DHCP_READY
");
#endif
}
if(!socket(SOCK_DHCP,Sn_MR_UDP,DHCP_CLIENT_PORT,0x00))/*初始化socket和端口*/
{
#ifdef DHCP_DEBUG
printf("Fail to create the DHCPC_SOCK(%u)
",SOCK_DHCP);
#endif
return DHCP_RET_ERR; /*socket初始化错误*/
}
}
switch ( dhcp_state )
{
case STATE_DHCP_READY:第四步 /*DHCP初始化状态*/
DHCP_timeout = 0; /*DHCP超时标志设置为1*/
reset_DHCP_time(); /*复位超时时间*/
send_DHCP_DISCOVER(); /*发送DISCOVER包*/
DHCP_timer = 0; /*set_timer0(DHCP_timer_handler); */
dhcp_state = STATE_DHCP_DISCOVER; /*DHCP的DISCOVER状态*/
printf("in>>STATE_DHCP_DISCOVER
");
break;
case STATE_DHCP_DISCOVER:第五步
if (type == DHCP_OFFER)
{
printf("input DHCP_OFFER>>
");
reset_DHCP_time(); /*复位超时时间*/
printf("input1 DHCP_OFFER>>
");
send_DHCP_REQUEST(); /*发送REQUEST包*/
printf("input2 DHCP_OFFER>>
");
dhcp_state = STATE_DHCP_REQUEST;
printf("STATE_DHCP_REQUEST DHCP_OFFER
");
#ifdef DHCP_DEBUG
printf("state : STATE_DHCP_REQUEST
");
#endif
}
else
printf("dhcp timeout
");
第六步check_DHCP_Timeout(); 一直是重复的 执行了
printf("check_DHCP_Timeout
");
break;
case STATE_DHCP_REQUEST : /*DHCP的REQUEST状态*/
if (type == DHCP_ACK) /*接收到DHCP服务器回应的off封包*/
{
reset_DHCP_time();
if (check_leasedIP())
{
#ifdef DHCP_DEBUG
printf("state : STATE_DHCP_LEASED
");
#endif
dhcp_state = STATE_DHCP_LEASED;
return DHCP_RET_UPDATE;
}
else
{
#ifdef DHCP_DEBUG
printf("state : STATE_DHCP_DISCOVER
");
#endif
dhcp_state = STATE_DHCP_DISCOVER;
return DHCP_RET_CONFLICT;
}
}
else if (type == DHCP_NAK)
{
reset_DHCP_time(); /*复位超时时间*/
dhcp_state = STATE_DHCP_DISCOVER;
#ifdef DHCP_DEBUG
printf("state : STATE_DHCP_DISCOVER
");
#endif
}
else
check_DHCP_Timeout(); /*检查是否超时*/
break;
case STATE_DHCP_LEASED :
if ((dhcp_lease_time != 0xffffffff) && (dhcp_time>(dhcp_lease_time/2)))
{
type = 0;
memcpy(OLD_SIP,GET_SIP,4);
DHCP_XID++;
send_DHCP_REQUEST();
dhcp_state = STATE_DHCP_REREQUEST;
#ifdef DHCP_DEBUG
printf("state : STATE_DHCP_REREQUEST
");
#endif
reset_DHCP_time();
}
break;
case STATE_DHCP_REREQUEST :
if (type == DHCP_ACK)
{
if(memcmp(OLD_SIP,GET_SIP,4)!=0)
{
#ifdef DHCP_DEBUG
printf("The IP address from the DHCP server is updated.
");
printf("OLD_SIP=%u.%u.%u.%u",OLD_SIP[0],OLD_SIP[1],OLD_SIP[2],OLD_SIP[3]);
printf("GET_SIP=%u.%u.%u.%u
",GET_SIP[0],GET_SIP[1],GET_SIP[2],GET_SIP[3]);
#endif
return DHCP_RET_UPDATE;
}
#ifdef DHCP_DEBUG
else
{
printf("state : STATE_DHCP_LEASED : same IP
");
}
#endif
reset_DHCP_time();
dhcp_state = STATE_DHCP_LEASED;
}
else if (type == DHCP_NAK)
{
reset_DHCP_time();
dhcp_state = STATE_DHCP_DISCOVER;
#ifdef DHCP_DEBUG
printf("state : STATE_DHCP_DISCOVER
");
#endif
}
else
check_DHCP_Timeout();
break;
default :
dhcp_state = STATE_DHCP_READY;
break;
}
if (DHCP_timeout == 1)
{
//kill_timer0(DHCP_timer);
dhcp_state = STATE_DHCP_READY;
return DHCP_RET_TIMEOUT;
}
第八步return DHCP_RET_NONE; /*一直返回获取失败*/
}
/**
*@brief 检查DHCP请求释放超时
*@param 无
*@return 无
*/
void check_DHCP_Timeout(void)
{
if (dhcp_retry_count < MAX_DHCP_RETRY) //dhcp_retry_count重试次数<3
{
if (dhcp_time > next_dhcp_time) //DHCP运行计数>DHCP超时时间 5
{
printf("in dhcp_time
");
dhcp_time = 0;
next_dhcp_time = dhcp_time + DHCP_WAIT_TIME; //5
dhcp_retry_count++;
switch ( dhcp_state )
{
case STATE_DHCP_DISCOVER :
//#ifdef DHCP_DEBUG
printf("<<timeout>> state : STATE_DHCP_DISCOVER
");
//#endif
第七步send_DHCP_DISCOVER();//发送DISCOVER信息给DHCP服务器 //发了也没用
break;
case STATE_DHCP_REQUEST :
//#ifdef DHCP_DEBUG
printf("<<timeout>> state : STATE_DHCP_REQUEST
");
//#endif
send_DHCP_REQUEST();
break;
case STATE_DHCP_REREQUEST :
//#ifdef DHCP_DEBUG
printf("<<timeout>> state : STATE_DHCP_REREQUEST
");
//#endif
send_DHCP_REQUEST();
break;
default :
break;
&n
2. SPI读W5500版本寄存器是否正常(默认0x04)
3. SPI写W5500 IP,子网掩码,网关,MAC4个寄存器,然后再读出来,确认SPI读写没有问题;
4. 使用PC(同网段) ping W5500看看能否ping 通。 Ps. W5500内部有ICMP协议,配置了第3步的4个寄存器就能ping通。
5. 前4步保证了物理连接和SPI正常。然后开始调Socket。 调Socket 需要关闭防火墙。
6. 配置Socket寄存器,然后和PC端的Socket程序连接。如果连接不上,这个时候可以用Wireshark分析原因。
7. 特别说一下,如果W5500通过路由器和远程服务器通信调试。可以使用一个集线器。将一台PC和W5500设备通过集线器接到路由器上面。这样PC运行的Wireshark就能抓到W5500设备和远程服务器的通信包,便于分析问题。
一周热门 更多>