LWIP_TCP如何理解數據發送,何時使用tcp_recved函數

這裏只講raw編程,如果你使用LWIP-socket或netconn,那就不存在這個問題,這些高級函數會自己在合適的地方調用tcp_recved函數。

問題的來源

對於初學者而言,LWIP收不到數據是個常見的問題。有不少網絡上流傳的源碼,一個典型的例子是tcp_echoserver。各個教學的資料中也都提供源碼。但很可惜,這些教學板提供的源碼缺乏可移植性。一具最常見的錯誤在於,大家對於什麼時候調用tcp_reved沒什麼概念。有不少源碼是在tcp_server_sent發送函數中調用該功能的。問題就是,如果用戶不是用來echo(立即發回相同的報文),而是真正要處理事務的時候,這種用法是錯誤的:此時,接收窗口大小由發送窗口決定,如果沒有發送新數據,接收窗口就會越來越小,直到最後無法接收數據。

正確的用法是:在收到數據後,應用層調用tcp_recved函數恢復原來的窗口大小;而在發送函數中,不用管窗口的事!

源碼全部貼在後面,這裏講解一些需要注意的地方

第一點

接收數據的PCB控制塊只能是tcp_active_pcbs上面的,而不是我們創建的那個用於tcp_listen的監聽控制塊,這個塊其實一直處於LISTEN狀態,是不能收發數據的。所以,如果你想在程序的任意位置發送信息,調用tcp_write(tcp_active_pcbs, ......) 是沒有問題的,當然要注意,如果你建立了多個鏈接,這裏tcp_active_pcbs只會使用到前面第一個。

通常,如果你要找的剛剛ESTALISHED的那個PCB,是在tcp_echoserver_accept中傳遞進來的,在下面的代碼中,就是這個,        pcb = tcp_echoserver_es->pcb;    

第二點

接收完數據後,調用tcp_recved擴大窗口。tcp_recved函數中,最關鍵的代碼是
pcb->rcv_wnd += len;
也就是恢復或擴大窗口的意思。爲什麼呢?

因爲tcp_receive函數在收到數據後,會把窗口縮小,表示接收數據的空間被剛收到的數據佔用了,所以你在tcp_receive中可以看到這樣的語句,
pcb->rcv_wnd -= tcplen;
pcb->rcv_wnd -= TCP_TCPLEN(cseg);

故而,在應用層處理完這些數據後,要通知LWIP,這些空間可以恢復到原來大小了,那些數據已經用過了。

源碼

源碼就不貼全部了,STM32CUBEMX配置就可以了,爲了方便,我隨便找個鏈接
https://blog.csdn.net/hustwf/article/details/80040578

按歸上面的做完了,把下面的代碼加進去就差不多了;如果還有,就是再把自己要用的如串口什麼自己加進去。

注意下面這個源碼也是從網絡上弄來的,但我改寫並增加了部分代碼:
1)print_msg函數是一個相當於重定位的printf到串口發送。網上隨便找一個都差不多。
2)養成習慣,收信息的地方只管收信息,絕不在收信息的函數中處理髮送問題;同樣,發信息的地方只管發信息,也不在這裏處理收信息的問題;這樣做的好處是,儘量解耦函數的功能,可以在任意地方在方便的時候處理消息。

DEMO中文有亂碼,無關緊要,湊和着看吧。

main.c

函數很簡單,MX_LWIP_Init(); 是自動生成的,調用初始化;User_notification(&gnetif); 是打印信息的;循環中使用按鍵0創建連接,1關閉連接。

int main(void)
{
	/* USER CODE BEGIN 1 */
	uint8_t  key = 0;
	HAL_DeInit();
	/* USER CODE END 1 */


	/* MCU Configuration--------------------------------------------------------*/

	/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
	HAL_Init();

	/* USER CODE BEGIN Init */

	/* USER CODE END Init */

	/* Configure the system clock */
	SystemClock_Config();

	/* USER CODE BEGIN SysInit */

	/* USER CODE END SysInit */

	/* Initialize all configured peripherals */
	MX_GPIO_Init();
	MX_DMA_Init();
	MX_USART1_UART_Init();
	MX_LWIP_Init();
	//MX_UART5_Init();
	/* USER CODE BEGIN 2 */	
    User_notification(&gnetif); 
	/* USER CODE END 2 */

	/* Infinite loop */
	/* USER CODE BEGIN WHILE */
	while (1)
	{
	/* USER CODE END WHILE */
		
		MX_LWIP_Process();      // <==> ethernetif_input(&gnetif);	sys_check_timeouts();
          
		key = key_scan(0);
		if(key == KEY0_PRES){
			tcp_echoserver_connect(); // create a receive/transmission connection
		}  
		if(key == KEY1_PRES){
			tcp_echoserver_close();
		}

		#ifdef USE_DHCP
		DHCP_Periodic_Handle(&gnetif);    
		#endif  

		// send out all received data!
		TransData(); 		
			
	/* USER CODE BEGIN 3 */
	}
	/* USER CODE END 3 */
}

tcp_echoserver.h

#ifndef __TCP_ECHOSERVER_H__
#define __TCP_ECHOSERVER_H__

/* °üº¬Í·Îļþ ----------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "tcp_def.h"
#include "stdio.h"
#include "string.h"

/* ÀàÐͶ¨Òå ------------------------------------------------------------------*/
// TCP server connection status 
enum tcp_echoserver_states
{
  ES_NONE = 0,
  ES_ACCEPTED,
  ES_RECEIVED,
  ES_CLOSING
};

// LwIP struct use by callback 
struct tcp_echoserver_struct
{
  u8_t state;             // current connection status
  u8_t retries;
  struct tcp_pcb *pcb;    // current pcb (protocol control block)
  struct pbuf *p;         // current receiving or transmission pbuf
};


#ifdef __cplusplus
extern "C" {
#endif

void     tcp_echoserver_connect(void);
void     tcp_echoserver_close(void);
int16_t  TcpProcessTransmission(uint8_t *pData, uint16_t Size);

#ifdef __cplusplus
}
#endif

#endif /* __TCP_ECHOSERVER */

/******************* (C) COPYRIGHT 2015-2020 ӲʯǶÈëʽ¿ª·¢ÍÅ¶Ó *****END OF FILE****/

tcp_echoserver.c

這裏只講一下TcpProcessTransmission這個函數,這個是我自己寫的,可以在程序的任意地方任何時候調用,用來發送數據的函數。

重點要注意的是, 在tcp_echoserver_recv中,有兩個地方我調用了tcp_recved函數。

/* °üº¬Í·Îļþ ----------------------------------------------------------------*/
#include "tcp_echoserver.h"

#if LWIP_TCP
// private type def --------------------------------------------------------------
struct tcp_pcb *tcp_echoserver_pcb = NULL;
struct tcp_echoserver_struct *tcp_echoserver_es = NULL;

// private macro ----------------------------------------------------------------
// private varaible--------------------------------------------------------------
uint8_t ServerIp[4];
uint8_t tcp_server_recvbuf[TCP_SERVER_RX_BUFSIZE];	

// PRIVATE FUNCTIONS-------------------------------------------------------------
static err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err);
static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
static void tcp_echoserver_error(void *arg, err_t err);
static err_t tcp_echoserver_poll(void *arg, struct tcp_pcb *tpcb);
static err_t tcp_echoserver_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
static void tcp_echoserver_send(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es);
static void tcp_echoserver_connection_close(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es);

// --------------------------------------------------------------------
/**
  * º¯Êý¹¦ÄÜ: TCP·þÎñÆ÷²âÊÔ
  * ÊäÈë²ÎÊý: ÎÞ
  * ·µ »Ø Öµ: ÎÞ
  * ˵    Ã÷: ÎÞ
  */
void tcp_echoserver_connect(void)
{
	main_flag &= ~((uint16_t)EMF_TCP_CONNECTED);
	tcp_echoserver_pcb = tcp_new();	

	if (tcp_echoserver_pcb != NULL)	{
		// printf("create a new pcb\n");
		err_t err;
    
		// bind local IP to designated port (TCP_SERVER_PORT)
		err = tcp_bind(tcp_echoserver_pcb, IP_ADDR_ANY, TCP_SERVER_PORT);
		if (err == ERR_OK){
			//printf(" binding pcb successfully\n");
			tcp_echoserver_pcb = tcp_listen(tcp_echoserver_pcb);  // tcp pcb listening / monitoring
			tcp_accept(tcp_echoserver_pcb, tcp_echoserver_accept);// Intialize LwIP tcp_accept callback
			main_flag |= EMF_TCP_CONNECTED;
		}
		else {
			memp_free(MEMP_TCP_PCB, tcp_echoserver_pcb);
			// printf("Binding pcb failed\n");
		}
	}
	else{
		// printf("create new pcb failed.\n");
	}
}

/**
* brief: ¹Ø±ÕTCPÁ¬½Ó
*/
void tcp_echoserver_close(void)
{
	tcp_echoserver_connection_close(tcp_echoserver_pcb, tcp_echoserver_es);
	//printf("¹Ø±Õtcp server\n");	
}

/**
* brief: LwIP callback of accept, recognizing link establishment!
* tcp_input --> tcp_process(pcb) --> TCP_EVENT_ACCEPT,
* NOTE: tcp_accept_pcb may not be the tcp_active_pcbs (here it is from tcp_active_pcbs)
*/
static err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{
	err_t ret_err;
	struct tcp_echoserver_struct *es;

	LWIP_UNUSED_ARG(arg);
	LWIP_UNUSED_ARG(err);

	// set new pcb priority
	tcp_setprio(newpcb, TCP_PRIO_MIN);

	// IMPORTANT NOTE: allocation struct mem for pcb information  control
	es = (struct tcp_echoserver_struct *)mem_malloc(sizeof(struct tcp_echoserver_struct));
	tcp_echoserver_es = es;
	if (es != NULL)
	{
		es->state = ES_ACCEPTED;    // rcv established
		es->pcb = newpcb;           // this is the established pcb!!! (pcb->state == ESTABLISHED)
		es->retries = 0;
		es->p = NULL;
		
		tcp_arg(newpcb, es); // es is now the new pcb parameters		
		tcp_recv(newpcb, tcp_echoserver_recv);    // init tcp_recv() callback		
		tcp_err(newpcb, tcp_echoserver_error);    // init tcp_err() callback		
		tcp_poll(newpcb, tcp_echoserver_poll, 1); // init tcp_poll callback

		ServerIp[0] =  newpcb->remote_ip.addr     & 0xff;   //IADDR4
		ServerIp[1] = (newpcb->remote_ip.addr>>8) & 0xff;  	//IADDR3
		ServerIp[2] = (newpcb->remote_ip.addr>>16)& 0xff; 	//IADDR2
		ServerIp[3] = (newpcb->remote_ip.addr>>24)& 0xff; 	//IADDR1 
		//printf("Á¬½ÓµÄµçÄÔ¶ËIPΪ£º%d %d %d %d\n",ServerIp[0],ServerIp[1],ServerIp[2],ServerIp[3]);
		
		ret_err = ERR_OK;
	}
	else
	{
		// close TCP link
		tcp_echoserver_connection_close(newpcb, es);
		// return the error code
		ret_err = ERR_MEM;
	}
	return ret_err;  
}

/**
* brief: TCP callback of receiving
*/
static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
	char *recdata=0;
	struct tcp_echoserver_struct *es;
	err_t ret_err;
 
	LWIP_ASSERT("arg != NULL",arg != NULL);
	es = (struct tcp_echoserver_struct *)arg;

	// if we receive an empty tcp frame from client => close connection
	if (p == NULL){
		// remote host closed connection
		es->state = ES_CLOSING;
		if(es->p == NULL){			
			tcp_echoserver_connection_close(tpcb, es);  // we're done sending, close connection
		}
		else
		{			
			tcp_sent(tpcb, tcp_echoserver_sent);   // we're not done yet, acknowledge received packet
			tcp_echoserver_send(tpcb, es);  // send remaining data
		}
		ret_err = ERR_OK;
	}
	// else : a non empty frame was received from client but for some reason err != ERR_OK 
	else if(err != ERR_OK)
	{
		// free received pbuf
		if (p != NULL)
		{
			es->p = NULL;
			pbuf_free(p);
		}
		ret_err = err;
	}
	else if(es->state == ES_ACCEPTED)
	{
		// first data chunk in p->payload 
		es->state = ES_RECEIVED;
		
		// store reference to incoming pbuf (chain) 
		es->p = p;
		
		// initialize LwIP tcp_sent callback function 
		tcp_sent(tpcb, tcp_echoserver_sent);
		
		recdata=(char *)malloc(p->len*sizeof(char));
		if(recdata!=NULL)
		{
		  memcpy(recdata, p->payload, p->len);
		  print_msg("TCP_Server_Rec:%s\n", recdata);
		}
		free(recdata);    // printf send out already.... 
		
		//-- commented out bymc
		// tcp_echoserver_send(tpcb, es);  // send back the received data (echo) 
				
		tcp_recved(tpcb, p->tot_len);  // added bymc
		pbuf_free(p);                  // added bymc
		es->p = NULL;                  // added bymc
		
		ret_err = ERR_OK;
	}
	else if (es->state == ES_RECEIVED)
	{
		// more data received from client and previous data has been already sent
		if(es->p == NULL)
		{
			es->p = p;
			recdata=(char *)malloc(p->len*sizeof(char)+1);
			if(recdata!=NULL)
			{
				memcpy(recdata, p->payload, p->len);
				recdata[p->len] = 0x0;
				print_msg("TCP_Server_Rec:%s\n",recdata);
			}
			free(recdata);  
			
			//-- commented out bymc
			//tcp_echoserver_send(tpcb, es); // send back received data 
			
			tcp_recved(tpcb, p->tot_len);    // added bymc
			pbuf_free(p);                    // added bymc
			es->p = NULL;                  // added bymc
		}
		else
		{
			struct pbuf *ptr;

			// chain pbufs to the end of what we recv'ed previously  
			ptr = es->p;
			pbuf_chain(ptr, p);
		}
		ret_err = ERR_OK;
	}
	else if(es->state == ES_CLOSING)
	{
		// odd case, remote side closing twice, trash data 
		tcp_recved(tpcb, p->tot_len);
		es->p = NULL;
		pbuf_free(p);
		ret_err = ERR_OK;
	}
	else
	{
		// unkown es->state, trash data
		tcp_recved(tpcb, p->tot_len);
		es->p = NULL;
		pbuf_free(p);
		ret_err = ERR_OK;
	}
	return ret_err;
}

/**
* brief: TCP´íÎó»Øµ÷º¯Êý
*/
static void tcp_echoserver_error(void *arg, err_t err)
{
	struct tcp_echoserver_struct *es;

	LWIP_UNUSED_ARG(err);

	es = (struct tcp_echoserver_struct *)arg;
	if (es != NULL)
	{
		/*  free es structure */
		mem_free(es);
	}
}

/**
* brief: TCP_poll»Øµ÷º¯Êý
*/
static err_t tcp_echoserver_poll(void *arg, struct tcp_pcb *tpcb)
{
	err_t ret_err;
	struct tcp_echoserver_struct * es;

	es = (struct tcp_echoserver_struct *)arg;
	if (es != NULL)
	{
		if (es->p != NULL)
		{
			tcp_sent(tpcb, tcp_echoserver_sent);
			// there is a remaining pbuf (chain) , try to send data
			tcp_echoserver_send(tpcb, es);
		}
		else
		{
			//* no remaining pbuf (chain)
			if(es->state == ES_CLOSING)
			{
				//  close tcp connection
				tcp_echoserver_connection_close(tpcb, es);
			}
		}
		ret_err = ERR_OK;
	}
	else
	{
		// nothing to be done
		tcp_abort(tpcb);
		ret_err = ERR_ABRT;
	}
	return ret_err;
}

/**
* brief: TCP·¢Ëͻص÷º¯Êý
*/
static err_t tcp_echoserver_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
	struct tcp_echoserver_struct *es;

	LWIP_UNUSED_ARG(len);

	es = (struct tcp_echoserver_struct *)arg;
	es->retries = 0;

	if(es->p != NULL)
	{
		// still got pbufs to send 
		tcp_sent(tpcb, tcp_echoserver_sent);
		tcp_echoserver_send(tpcb, es);
	}
	else
	{
		// if no more data to send and client closed connection
		if(es->state == ES_CLOSING)
			tcp_echoserver_connection_close(tpcb, es);
	}
	return ERR_OK;
}

/**
* brief: TCP·¢ËÍÊý¾Ýº¯Êý
*/
static void tcp_echoserver_send(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es)
{
	struct pbuf *ptr;
	err_t wr_err = ERR_OK;

	while ((wr_err == ERR_OK) &&
		 (es->p != NULL) && 
		 (es->p->len <= tcp_sndbuf(tpcb)))
	{
		// get pointer on pbuf from es structure
		ptr = es->p;

		// enqueue data for transmission
		wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);

		if (wr_err == ERR_OK)
		{
			u16_t plen;
			u8_t freed;

			plen = ptr->len;

			// continue with next pbuf in chain (if any)
			es->p = ptr->next;

			if(es->p != NULL){
				// increment reference count for es->p
				pbuf_ref(es->p);
			}

			// chop first pbuf from chain
			do
			{
				// try hard to free pbuf
				freed = pbuf_free(ptr);
			} while(freed == 0);
			
			// we can read more data now
			tcp_recved(tpcb, plen);			
		}
		else if(wr_err == ERR_MEM)
		{
			// we are low on memory, try later / harder, defer to poll 
			es->p = ptr;
			tcp_output(tpcb);   
		}
		else
		{
			// other problem ?? 
		}
	}
}

/**
* brief: ¹Ø±ÕTCPÁ¬½Óº¯Êý
*/
static void tcp_echoserver_connection_close(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es)
{  
	/* remove all callbacks */
	tcp_arg(tpcb, NULL);
	tcp_sent(tpcb, NULL);
	tcp_recv(tpcb, NULL);
	tcp_err(tpcb, NULL);
	tcp_poll(tpcb, NULL, 0);

	/* delete es structure */
	if (es != NULL)
	{
		mem_free(es);
	}  

	/* close tcp connection */
	tcp_close(tpcb);
	
	main_flag &= ~((uint16_t)EMF_TCP_CONNECTED);
}

int16_t TcpProcessTransmission(uint8_t *pData, uint16_t Len){
	err_t wr_err = ERR_OK;
	struct tcp_pcb * pcb = NULL;
	if(tcp_echoserver_es){
		pcb = tcp_echoserver_es->pcb;	
	}
	
	if(pcb && (main_flag & EMF_TCP_CONNECTED)){
		wr_err = tcp_write(pcb, pData, Len, 1);
		if (wr_err == ERR_OK)
		{	
			// we can read more data now
			// tcp_recved(pcb, Len);			
		}
		else if(wr_err == ERR_MEM)
		{
			// we are low on memory, try later / harder, defer to poll 			
			tcp_output(pcb);   
		}
		else
		{
			// other problem ?? 
		}
		return Len;
	}
	return 0;
}

#endif /* LWIP_TCP */

app_ethernet.h

#ifndef __APP_ETHERNET_H
#define __APP_ETHERNET_H

/* °üº¬Í·Îļþ ----------------------------------------------------------------*/
#include "lwip/netif.h"
#include "tcp_def.h"
   
/* ÀàÐͶ¨Òå ------------------------------------------------------------------*/
/* ºê¶¨Òå --------------------------------------------------------------------*/
#define DHCP_OFF                   (uint8_t) 0
#define DHCP_START                 (uint8_t) 1
#define DHCP_WAIT_ADDRESS          (uint8_t) 2
#define DHCP_ADDRESS_ASSIGNED      (uint8_t) 3
#define DHCP_TIMEOUT               (uint8_t) 4
#define DHCP_LINK_DOWN             (uint8_t) 5
   
/* À©Õ¹±äÁ¿ ------------------------------------------------------------------*/
/* º¯ÊýÉùÃ÷ ------------------------------------------------------------------*/

#ifdef __cplusplus
extern "C" {
#endif

void User_notification(struct netif *netif);
#ifdef USE_DHCP
void DHCP_Process(struct netif *netif);
void DHCP_Periodic_Handle(struct netif *netif);
#endif  

#ifdef __cplusplus
}
#endif

#endif /* __APP_ETHERNET_H */


/******************* (C) COPYRIGHT 2015-2020 ӲʯǶÈëʽ¿ª·¢ÍÅ¶Ó *****END OF FILE****/

app_ethernet.c

/* °üº¬Í·Îļþ ----------------------------------------------------------------*/
#include <string.h>
#include "stm32f4xx_hal.h"
#include "lwip/dhcp.h"
#include "app_ethernet.h"

#ifdef USE_DHCP
#define MAX_DHCP_TRIES  4
extern uint32_t DHCPfineTimer; // = 0;
__IO uint8_t DHCP_state = DHCP_OFF;
__IO uint8_t DHCP_flag=0;
#endif

/**
* brief: test tcp server. semd IP address info on netif-up
*/
void User_notification(struct netif *netif) 
{	
	if (netif_is_up(netif)){
		#ifdef USE_DHCP		
		DHCP_state = DHCP_START;   // Update DHCP state machine
		print_msg("IP address: %s\n", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
		#else
		uint8_t iptxt[20];
		sprintf((char *)iptxt, "%s", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
		printf ("Static IP address: %s\n", iptxt);
		#endif // USE_DHCP 
	}
	else{  
		#ifdef USE_DHCP
		DHCP_state = DHCP_LINK_DOWN; // Update DHCP state machine
		#endif  // USE_DHCP
		print_msg("The network cable is not connected \n");
	} 
}

/**
  * º¯Êý¹¦ÄÜ: ¶ÔÁ´½Ó״̬½øÐÐ֪ͨ
  * ÊäÈë²ÎÊý: ÎÞ
  * ·µ »Ø Öµ: ÎÞ
  * ˵    Ã÷: ÎÞ
  */
void ethernetif_notify_conn_changed(struct netif *netif)
{
	#ifndef USE_DHCP
	ip_addr_t ipaddr;
	ip_addr_t netmask;
	ip_addr_t gw;
	#endif
  
	if(netif_is_link_up(netif))
	{
		print_msg("The network cable is now connected \n");
    
		#ifdef USE_DHCP		
		DHCP_state = DHCP_START;  // Update DHCP state machine
		#else
		IP_ADDR4(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
		IP_ADDR4(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);
		IP_ADDR4(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);  

		netif_set_addr(netif, &ipaddr , &netmask, &gw);  
		 
		uint8_t iptxt[20];
		sprintf((char *)iptxt, "%s", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
		printf ("Static IP address: %s\n", iptxt);
		#endif // USE_DHCP
		netif_set_up(netif);     // When the netif is fully configured this function must be called.
		print_msg("IP address: %s\n", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
	} 
	else
	{
		#ifdef USE_DHCP
		DHCP_state = DHCP_LINK_DOWN;   // Update DHCP state machine
		#endif // USE_DHCP
    
        netif_set_down(netif);  //  When the netif link is down this function must be called.
		print_msg ("The network cable is not connected.\n");
	}
}

#ifdef USE_DHCP
/**
*brief: retrieve DHCP
*/
void DHCP_Process(struct netif *netif)
{
	ip_addr_t ipaddr;
	ip_addr_t netmask;
	ip_addr_t gw;
	struct dhcp *dhcp;   
	
	switch (DHCP_state)
	{
	case DHCP_START:
    {
		ip_addr_set_zero_ip4(&netif->ip_addr);
		ip_addr_set_zero_ip4(&netif->netmask);
		ip_addr_set_zero_ip4(&netif->gw);
		DHCP_state = DHCP_WAIT_ADDRESS;
		dhcp_start(netif);
		print_msg("State: Looking for DHCP server ...\n");
		break;
    }
	case DHCP_WAIT_ADDRESS:
    {
		if (dhcp_supplied_address(netif)) 
		{
			DHCP_state = DHCP_ADDRESS_ASSIGNED;

			print_msg("IP address assigned by a DHCP server: %s\n", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
			DHCP_flag=1;
		}
        else
		{
			dhcp = (struct dhcp *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);

			// DHCP timeout
			if (dhcp->tries > MAX_DHCP_TRIES)
			{
				DHCP_state = DHCP_TIMEOUT;

				// Stop DHCP
				dhcp_stop(netif);

				// Static address used
				IP_ADDR4(&ipaddr, IP_ADDR0 ,IP_ADDR1 , IP_ADDR2 , IP_ADDR3 );
				IP_ADDR4(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
				IP_ADDR4(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
				netif_set_addr(netif, &ipaddr, &netmask, &gw);
				  
				print_msg("DHCP Timeout !! \n");
				print_msg("Static IP address: %s\n", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
			}
		}
		break;
	} 
	case DHCP_LINK_DOWN:
    {
		// Stop DHCP
		dhcp_stop(netif);
		DHCP_state = DHCP_OFF;
		break;
	}
	default: break;
	}
}

/**
  * º¯Êý¹¦ÄÜ: DHCPÂÖѯ
  * ÊäÈë²ÎÊý: ÎÞ
  * ·µ »Ø Öµ: ÎÞ
  * ˵    Ã÷: ÎÞ
  */
void DHCP_Periodic_Handle(struct netif *netif)
{  
	// Fine DHCP periodic process every 500ms
	if (HAL_GetTick() - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS)
	{
		DHCPfineTimer =  HAL_GetTick();		
		DHCP_Process(netif);    // process DHCP state machine
	}
}
#endif

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章