服务器怎么设置ip做网站,凌云seo博客,京东网站 用什么做的,新手怎么建立自己的网站1.DHCP协议介绍#xff1a; DHCP#xff08;Dynamic Host Configuration Protocol#xff09;是一种用于自动分配IP地址和其他网络配置信息的协议。它允许网络中的设备#xff08;如计算机、手机、打印机等#xff09;在连接到网络时自动获取IP地址、子网掩码、默认网关、…1.DHCP协议介绍 DHCPDynamic Host Configuration Protocol是一种用于自动分配IP地址和其他网络配置信息的协议。它允许网络中的设备如计算机、手机、打印机等在连接到网络时自动获取IP地址、子网掩码、默认网关、DNS服务器等信息而无需手动配置。
DHCP工作原理是通过DHCP服务器向网络中的设备提供IP地址和其他配置信息。当设备连接到网络时它会发送一个DHCP请求请求一个可用的IP地址和其他配置信息。DHCP服务器收到请求后会分配一个可用的IP地址并将其他配置信息一并发送给设备使设备能够顺利地加入到网络中。
DHCP的优点是简化了网络管理减少了手动配置的工作量同时也提高了网络的灵活性和可扩展性。通过DHCP管理员可以更轻松地管理网络中的设备并且可以更快速地进行网络扩展和变更。
2.DHCP报文
DHCP报文种类
DHCP一共有8中报文各种类型报文的基本功能如下
报文类型说明Discover0x01 DHCP客户端在请求IP地址时并不知道DHCP服务器的位置因此DHCP客户端会在本地网络内以广播方式发送Discover请求报文以发现网络中的DHCP服务器。所有收到Discover报文的DHCP服务器都会发送应答报文DHCP客户端据此可以知道网络中存在的DHCP服务器的位置。Offer0x02DHCP服务器收到Discover报文后就会在所配置的地址池中查找一个合适的IP地址加上相应的租约期限和其他配置信息如网关、DNS服务器等构造一个Offer报文发送给DHCP客户端告知用户本服务器可以为其提供IP地址。但这个报文只是告诉DHCP客户端可以提供IP地址最终还需要客户端通过ARP来检测该IP地址是否重复。Request0x03 DHCP客户端可能会收到很多Offer请求报文所以必须在这些应答中选择一个。通常是选择第一个Offer应答报文的服务器作为自己的目标服务器并向该服务器发送一个广播的Request请求报文通告选择的服务器希望获得所分配的IP地址。另外DHCP客户端在成功获取IP地址后在地址使用租期达到50%时会向DHCP服务器发送单播Request请求报文请求续延租约如果没有收到ACK报文在租期达到87.5%时会再次发送广播的Request请求报文以请求续延租约。Decline0x04DHCP客户端收到DHCP服务器ACK应答报文后通过地址冲突检测发现服务器分配的地址冲突或者由于其他原因导致不能使用则会向DHCP服务器发送Decline请求报文通知服务器所分配的IP地址不可用以期获得新的IP地址。ACK0x05 DHCP服务器收到Request请求报文后根据Request报文中携带的用户MAC来查找有没有相应的租约记录如果有则发送ACK应答报文通知用户可以使用分配的IP地址。NAK0x06如果DHCP服务器收到Request请求报文后没有发现有相应的租约记录或者由于某些原因无法正常分配IP地址则向DHCP客户端发送NAK应答报文通知用户无法分配合适的IP地址。Release0x07 当DHCP客户端不再需要使用分配IP地址时一般出现在客户端关机、下线等状况就会主动向DHCP服务器发送RELEASE请求报文告知服务器用户不再需要分配IP地址请求DHCP服务器释放对应的IP地址。Inform0x08 DHCP客户端如果需要从DHCP服务器端获取更为详细的配置信息则向DHCP服务器发送Inform请求报文DHCP服务器在收到该报文后将根据租约进行查找到相应的配置信息后向DHCP客户端发送ACK应答报文。目前基本上不用了。
DHCP报文格式 字段长度说明op1byte是报文的操作类型分为请求报文和响应报文1为请求报文2为响应报文。具体的报文类型在option字段中标识。htype1byte硬件地址的长度以太网的硬件地址长度为6bytes。hlen1byte硬件地址的长度以太网的硬件地址长度为6bytes。hops1byte表示当前dhcp报文经过的DHCP中继的数目每经过一个DHCP中继这个字段就加1.xid4bytes由client端产生的随机数用于匹配请求和应答报文就是匹配应答报文是对哪个请求报文做出应答。secs2bytes客户端进入IP地址申请进程的时间或者更新IP地址进程的时间由客户端软件根据情况设定。目前没有使用固定为0。flags2bytes是标志字段16比特中只使用了最高位比特即最左边的比特这个个比特是广播响应标识位用来标识DHCP服务器发出的响应报文是广播还是单播0是单播1是广播。其余的比特位保留不用都为0.ciaddr4bytes是客户端的IP地址可以是client自己的IP地址也可以是server分配给client的IP地址。yiaddr4bytes(Your IP Address)是server分配给client的IP地址。siaddr4bytes是client端获取IP地址等信息的server端的地址。giaddr4bytes是client发出请求报文后经过的第一个中继的IP地址。chaddr16bytes是client端的硬件地址在client发出报文时会把自己网卡的硬件地址写进这个字段。sname64bytes服务器主机名是client端获取IP地址等信息的服务器名称。file128bytes是client的启动配置文件名是服务器为client指定的启动配置文件名及路径信息由服务器填写。options可变是可选变长的选项字段这个字段包含了终端的初始配置信息和网络配置信息包括报文类型有效租期DNS服务器的IP地址等配置信息。 2.DHCP流程 DHCP的流程分为四个阶段
分别是
1.发现阶段DHCP客户端向DHCP服务端发送DHCP_DISCOVER报文。
2.提供阶段DHCP服务端收到客户端DHCP_DISCOVER报文后向发送DHCP客户端发送DHCP_OFFER报文,该报文中包含尚未分配的地址信息。
3.选择阶段DHCP客户端选择IP地址然后广播发送DHCP_REQUEST包宣告使用它挑选的DHCP服务器地址并正式请求DHCP服务器分配地址
4.确认阶段当DHCP服务器收到DHCP客户端的DHCP_REQUEST包后便向客户端发送包含它所提供的IP地址及其他配置信息的DHCPACK确认包。
3.代码分析
首先初始化单片机的外设时钟、spi、uart、24c02、配置w5500参数等。
然后调用函数init_dhcp_client函数对DHCP进行初始化主要设置ip、mac等信息把dhcp_state状态设置为STATE_DHCP_READY
void init_dhcp_client(void)
{uint8 txsize[MAX_SOCK_NUM] {2, 2, 2, 2, 2, 2, 2, 2};uint8 rxsize[MAX_SOCK_NUM] {2, 2, 2, 2, 2, 2, 2, 2};//uint8 ip_broadcast[4]{255,};uint8 ip_0[4] {0,};DHCP_XID 0x12345678;memset(OLD_SIP, 0, sizeof(OLD_SIP));memset(DHCP_SIP, 0, sizeof(DHCP_SIP));memset(DHCP_REAL_SIP, 0, sizeof(GET_SN_MASK));iinchip_init();setSHAR(ConfigMsg.mac);setSUBR(ip_0);setGAR(ip_0);setSIPR(ip_0);printf(MAC%02x:%02x:%02x:%02x:%02x:%02x\r\n, DHCP_CHADDR[0], DHCP_CHADDR[1], DHCP_CHADDR[2], DHCP_CHADDR[3], DHCP_CHADDR[4], DHCP_CHADDR[5]);sysinit(txsize, rxsize);//clear ip setted flagdhcp_state STATE_DHCP_READY;#ifdef _DHCP_DEBUGprintf(init_dhcp_client:%u\r\n, SOCK_DHCP);#endif
}
进入while循环执行DHCP_run()函数
uint8_t DHCP_run(void)
{uint8_t type;uint8_t ret;if(dhcp_state STATE_DHCP_STOP) return DHCP_STOPPED;if(getSn_SR(SOCK_DHCP) ! SOCK_UDP)socket(SOCK_DHCP, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00);ret DHCP_RUNNING;type parseDHCPMSG();switch ( dhcp_state ){case STATE_DHCP_READY :DHCP_allocated_ip[0] 0;DHCP_allocated_ip[1] 0;DHCP_allocated_ip[2] 0;DHCP_allocated_ip[3] 0;send_DHCP_DISCOVER();dhcp_time 0;dhcp_state STATE_DHCP_DISCOVER;break;case STATE_DHCP_DISCOVER :if (type DHCP_OFFER){#ifdef _DHCP_DEBUG_printf( Receive DHCP_OFFER\r\n);#endifDHCP_allocated_ip[0] pDHCPMSG-yiaddr[0];DHCP_allocated_ip[1] pDHCPMSG-yiaddr[1];DHCP_allocated_ip[2] pDHCPMSG-yiaddr[2];DHCP_allocated_ip[3] pDHCPMSG-yiaddr[3];send_DHCP_REQUEST();dhcp_time 0;dhcp_state STATE_DHCP_REQUEST;}elseret check_DHCP_timeout();break;case STATE_DHCP_REQUEST :if (type DHCP_ACK){#ifdef _DHCP_DEBUG_printf( Receive DHCP_ACK\r\n);#endifif (check_DHCP_leasedIP()){// Network info assignment from DHCPprintf(ip:%d.%d.%d.%d\r\n, DHCP_allocated_ip[0], DHCP_allocated_ip[1], DHCP_allocated_ip[2], DHCP_allocated_ip[3]);printf(sn:%d.%d.%d.%d\r\n, DHCP_allocated_sn[0], DHCP_allocated_sn[1], DHCP_allocated_sn[2], DHCP_allocated_sn[3]);printf(gw:%d.%d.%d.%d\r\n, DHCP_allocated_gw[0], DHCP_allocated_gw[1], DHCP_allocated_gw[2], DHCP_allocated_gw[3]);dhcp_ip_assign();reset_DHCP_timeout();dhcp_state STATE_DHCP_LEASED;}else{// IP address conflict occurredreset_DHCP_timeout();dhcp_ip_conflict();dhcp_state STATE_DHCP_READY;}}else if (type DHCP_NAK){#ifdef _DHCP_DEBUG_printf( Receive DHCP_NACK\r\n);#endifreset_DHCP_timeout();dhcp_state STATE_DHCP_DISCOVER;}elseret check_DHCP_timeout();break;case STATE_DHCP_LEASED :ret DHCP_IP_LEASED;if ((dhcp_lease_time ! DEFAULT_LEASETIME) ((dhcp_lease_time / 2) dhcp_time)){#ifdef _DHCP_DEBUG_printf( Maintains the IP address \r\n);#endiftype 0;OLD_allocated_ip[0] DHCP_allocated_ip[0];OLD_allocated_ip[1] DHCP_allocated_ip[1];OLD_allocated_ip[2] DHCP_allocated_ip[2];OLD_allocated_ip[3] DHCP_allocated_ip[3];DHCP_XID;send_DHCP_REQUEST();reset_DHCP_timeout();dhcp_state STATE_DHCP_REREQUEST;}break;case STATE_DHCP_REREQUEST :ret DHCP_IP_LEASED;if (type DHCP_ACK){dhcp_retry_count 0;if (OLD_allocated_ip[0] ! DHCP_allocated_ip[0] ||OLD_allocated_ip[1] ! DHCP_allocated_ip[1] ||OLD_allocated_ip[2] ! DHCP_allocated_ip[2] ||OLD_allocated_ip[3] ! DHCP_allocated_ip[3]){ret DHCP_IP_CHANGED;dhcp_ip_update();#ifdef _DHCP_DEBUG_printf(IP changed.\r\n);#endif}#ifdef _DHCP_DEBUG_else printf(IP is continued.\r\n);#endifreset_DHCP_timeout();dhcp_state STATE_DHCP_LEASED;}else if (type DHCP_NAK){#ifdef _DHCP_DEBUG_printf( Receive DHCP_NACK, Failed to maintain ip\r\n);#endifreset_DHCP_timeout();dhcp_state STATE_DHCP_DISCOVER;}else ret check_DHCP_timeout();break;default :break;}return ret;
}
分析DHCP_run函数
1. 打开socket,调用parseDHCPMSG()函数接受数据并解析将收到的数据进行保存。
int8_t parseDHCPMSG(void)//20180625
{uint8_t svr_addr[6];uint16_t svr_port;uint16_t len;uint8_t * p;uint8_t * e;uint8_t type;uint8_t opt_len;if((len getSn_RX_RSR(SOCK_DHCP)) 0){len recvfrom(SOCK_DHCP, (uint8_t *)pDHCPMSG, len, svr_addr, svr_port);#ifdef _DHCP_DEBUG_printf(DHCP message : %d.%d.%d.%d(%d) %d received. \r\n, svr_addr[0], svr_addr[1], svr_addr[2], svr_addr[3], svr_port, len);#endif}else return 0;if (svr_port DHCP_SERVER_PORT){// compare mac addressif ( (pDHCPMSG-chaddr[0] ! DHCP_CHADDR[0]) || (pDHCPMSG-chaddr[1] ! DHCP_CHADDR[1]) ||(pDHCPMSG-chaddr[2] ! DHCP_CHADDR[2]) || (pDHCPMSG-chaddr[3] ! DHCP_CHADDR[3]) ||(pDHCPMSG-chaddr[4] ! DHCP_CHADDR[4]) || (pDHCPMSG-chaddr[5] ! DHCP_CHADDR[5]) )return 0;type 0;p (uint8_t *)(pDHCPMSG-op);//2p p 240; // 240 sizeof(RIP_MSG) MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt)e p (len - 240);while ( p e ){switch ( *p ){case endOption :p e; // for break while(p e)break;case padOption :p;break;case dhcpMessageType :p;p;type *p;break;case subnetMask :p;p;DHCP_allocated_sn[0] *p;DHCP_allocated_sn[1] *p;DHCP_allocated_sn[2] *p;DHCP_allocated_sn[3] *p;break;case routersOnSubnet :p;opt_len *p;DHCP_allocated_gw[0] *p;DHCP_allocated_gw[1] *p;DHCP_allocated_gw[2] *p;DHCP_allocated_gw[3] *p;p p (opt_len - 4);break;case dns :p;opt_len *p;DHCP_allocated_dns[0] *p;DHCP_allocated_dns[1] *p;DHCP_allocated_dns[2] *p;DHCP_allocated_dns[3] *p;p p (opt_len - 4);break;case dhcpIPaddrLeaseTime :p;opt_len *p;dhcp_lease_time *p;dhcp_lease_time (dhcp_lease_time 8) *p;dhcp_lease_time (dhcp_lease_time 8) *p;dhcp_lease_time (dhcp_lease_time 8) *p;#ifdef _DHCP_DEBUG_// dhcp_lease_time 10;// printf(dhcp_lease_time:%d\r\n,(int)dhcp_lease_time);#endifbreak;case dhcpServerIdentifier :p;opt_len *p;DHCP_SIP[0] *p;DHCP_SIP[1] *p;DHCP_SIP[2] *p;DHCP_SIP[3] *p;break;default :p;opt_len *p;p opt_len;break;} // switch} // while} // ifreturn type;
}
2.然后进入switch状态机首先dhcp_state的值为STATE_DHCP_READY执行一下代码
进入发现阶段DHCP客户端向DHCP服务端发送DHCP_DISCOVER报文,然后把dhcp_state的值设为STATE_DHCP_DISCOVER。 case STATE_DHCP_READY :DHCP_allocated_ip[0] 0;DHCP_allocated_ip[1] 0;DHCP_allocated_ip[2] 0;DHCP_allocated_ip[3] 0;send_DHCP_DISCOVER();dhcp_time 0;dhcp_state STATE_DHCP_DISCOVER;break;
3.然后退出switch,再次调用parseDHCPMSG()函数去接受DHCP服务端发来的数据并解析再次进入switch状态机中执行STATE_DHCP_DISCOVER代码如果数据包的类型是DHCP_OFFER
就执行以下代码DHCP客户端选择IP地址然后广播发送DHCP_REQUEST包宣告使用它挑选的DHCP服务器地址并正式请求DHCP服务器分配地址。 case STATE_DHCP_DISCOVER :if (type DHCP_OFFER){#ifdef _DHCP_DEBUG_printf( Receive DHCP_OFFER\r\n);#endifDHCP_allocated_ip[0] pDHCPMSG-yiaddr[0];DHCP_allocated_ip[1] pDHCPMSG-yiaddr[1];DHCP_allocated_ip[2] pDHCPMSG-yiaddr[2];DHCP_allocated_ip[3] pDHCPMSG-yiaddr[3];send_DHCP_REQUEST();dhcp_time 0;dhcp_state STATE_DHCP_REQUEST;} 4.如果正确接收到DHCP服务端的DHAP_ACK数据包则DHCP请求就成功了。执行一下代码
若是DHAP_ACK数据包则调用check_DHCP_leasedIP()函数检查IP是否有效然后我们去设置w5500的IP等信息把dhcp_state状态设为STATE_DHCP_LEASED,若是DHCP_NAK数据包调用reset_DHCP_timeout()把超时时间复位, 然后将dhcp_state值改为STATE_DHCP_DISCOVER重新进入发现阶段。 case STATE_DHCP_REQUEST :if (type DHCP_ACK){#ifdef _DHCP_DEBUG_printf( Receive DHCP_ACK\r\n);#endifif (check_DHCP_leasedIP()){// Network info assignment from DHCPprintf(ip:%d.%d.%d.%d\r\n, DHCP_allocated_ip[0], DHCP_allocated_ip[1], DHCP_allocated_ip[2], DHCP_allocated_ip[3]);printf(sn:%d.%d.%d.%d\r\n, DHCP_allocated_sn[0], DHCP_allocated_sn[1], DHCP_allocated_sn[2], DHCP_allocated_sn[3]);printf(gw:%d.%d.%d.%d\r\n, DHCP_allocated_gw[0], DHCP_allocated_gw[1], DHCP_allocated_gw[2], DHCP_allocated_gw[3]);dhcp_ip_assign();reset_DHCP_timeout();dhcp_state STATE_DHCP_LEASED;}else{// IP address conflict occurredreset_DHCP_timeout();dhcp_ip_conflict();dhcp_state STATE_DHCP_READY;}}else if (type DHCP_NAK){#ifdef _DHCP_DEBUG_printf( Receive DHCP_NACK\r\n);#endifreset_DHCP_timeout();dhcp_state STATE_DHCP_DISCOVER;}elseret check_DHCP_timeout();break;
05_W5500_UDP通信 --------- 上一篇 下一篇---------- 07——W5500