STM32 裸机 LWIP RAW接口 TCP客户端和服务端,以及UDP收发实现

avatar
作者
猴君
阅读量:0

RAW接口

RAW/Callback API 是 LwIP 的一大特色, 在没有操作系统支持的裸机环境中,只能使用这种 API 进行开发;此文章基于野火LWIP教程记录使用方法;使用CubeMX生成LWIP项目,1分钟就可实现TCP、UDP通信;很方便。

关于网线热插拔:我使用CubeMX生成的LWIP裸机项目中发现,网线热插拔在MX_LWIP_Process();已经做了相关处理。直接在轮询中调用即可。

/**  * ----------------------------------------------------------------------  * Function given to help user to continue LwIP Initialization  * Up to user to complete or change this function ...  * Up to user to call this function in main.c in while (1) of main(void)  *-----------------------------------------------------------------------  * Read a received packet from the Ethernet buffers  * Send it to the lwIP stack for handling  * Handle timeouts if LWIP_TIMERS is set and without RTOS  * Handle the llink status if LWIP_NETIF_LINK_CALLBACK is set and without RTOS  */ void MX_LWIP_Process(void) { /* USER CODE BEGIN 4_1 */ /* USER CODE END 4_1 */   ethernetif_input(&gnetif);  /* USER CODE BEGIN 4_2 */ /* USER CODE END 4_2 */   /* Handle timeouts */   sys_check_timeouts();    Ethernet_Link_Periodic_Handle(&gnetif); //检测网线连接状态  /* USER CODE BEGIN 4_3 */ /* USER CODE END 4_3 */ } 

使用方法,MAIN函数部分。

  /* Initialize all configured peripherals */   MX_GPIO_Init();   MX_LWIP_Init();   /* USER CODE BEGIN 2 */     TCP_Client_Init(); //TCP客户端    TCP_Server_Init();  //TCP服务端    UDP_Echo_Init();  //UDP通信   /* USER CODE END 2 */    /* Infinite loop */   /* USER CODE BEGIN WHILE */   while (1)   { 	 if(tick_1ms) 	 { 		MX_LWIP_Process();     /* USER CODE END WHILE */      /* USER CODE BEGIN 3 */ 		tick_1ms = false; 	 }    } 

TCP 客户端

#include "tcpclient.h" #include "lwip/netif.h" #include "lwip/ip.h" #include "lwip/tcp.h" #include "lwip/init.h" #include "netif/etharp.h" #include "lwip/udp.h" #include "lwip/pbuf.h" #include <stdio.h>	 #include <string.h>  #define TCP_CLIENT_PORT 5001 void TCP_Client_Init(void);   static struct tcp_pcb *client_pcb = NULL;  static void client_err(void *arg, err_t err) {   printf("connect error! closed by core!!\n"); 	printf("try to connect to server again!!\n");      //连接失败的时候释放TCP控制块的内存   tcp_close(client_pcb);        //重新连接   TCP_Client_Init(); }   static err_t client_send(void *arg, struct tcp_pcb *tpcb) {   uint8_t send_buf[]= "This is a TCP Client test...\n";      //发送数据到服务器   tcp_write(tpcb, send_buf, sizeof(send_buf), 1);       return ERR_OK; }  static err_t client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {   if (p != NULL)    {             /* 接收数据*/     tcp_recved(tpcb, p->tot_len);            /* 返回接收到的数据*/       tcp_write(tpcb, p->payload, p->tot_len, 1);            memset(p->payload, 0 , p->tot_len);     pbuf_free(p);   }    else if (err == ERR_OK)    {     //服务器断开连接     printf("server has been disconnected!\n");     tcp_close(tpcb);          //重新连接     TCP_Client_Init();   }   return ERR_OK; }  static err_t client_connected(void *arg, struct tcp_pcb *pcb, err_t err) {   printf("connected ok!\n");      //注册一个周期性回调函数   tcp_poll(pcb,client_send,2);      //注册一个接收函数   tcp_recv(pcb,client_recv);      return ERR_OK; }   void TCP_Client_Init(void) {           ip4_addr_t server_ip;   /* 创建一个TCP控制块  */   client_pcb = tcp_new();	      IP4_ADDR(&server_ip, DEST_IP_ADDR0,DEST_IP_ADDR1,DEST_IP_ADDR2,DEST_IP_ADDR3);    printf("client start connect!\n");      //开始连接   tcp_connect(client_pcb, &server_ip, TCP_CLIENT_PORT, client_connected);       //注册异常处理   tcp_err(client_pcb, client_err); 	      } 

TCP服务端

#include "tcpserver.h" #include "lwip/netif.h" #include "lwip/ip.h" #include "lwip/tcp.h" #include "lwip/init.h" #include "netif/etharp.h" #include "lwip/udp.h" #include "lwip/pbuf.h" #include <stdio.h>	 #include <string.h>  #define TCP_Server_PORT 5001 void TCP_Server_Init(void);  static err_t tcpecho_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {   if (p != NULL)    {         	/* 更新窗口*/ 	tcp_recved(tpcb, p->tot_len);          /* 返回接收到的数据*/     tcp_write(tpcb, p->payload, p->tot_len, 1);        memset(p->payload, 0 , p->tot_len);   pbuf_free(p);        }    else if (err == ERR_OK)    {     return tcp_close(tpcb);   }   return ERR_OK; }  static err_t tcpecho_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {         tcp_recv(newpcb, tcpecho_recv);   return ERR_OK; }  void TCP_Server_Init(void) {   struct tcp_pcb *pcb = NULL;	            		      /* 创建一个TCP控制块  */   pcb = tcp_new();	        /* 绑定TCP控制块 */   tcp_bind(pcb, IP_ADDR_ANY, TCP_Server_PORT );            /* 进入监听状态 */   pcb = tcp_listen(pcb);				    /* 处理连接 */	   tcp_accept(pcb, tcpecho_accept);    }  

UDP通信

搞不懂,UDP是无连接通信,不区分服务器和客户端;但是总有人分客户端和服务端。

#include "udpecho.h" #include "lwip/netif.h" #include "lwip/ip.h" #include "lwip/tcp.h" #include "lwip/init.h" #include "netif/etharp.h" #include "lwip/udp.h" #include "lwip/pbuf.h" #include <stdio.h>	 #include <string.h>	  #define UDP_ECHO_PORT 5001 void UDP_Echo_Init(void);  static void udp_demo_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) {    struct pbuf *q = NULL;    const char* reply = "This is reply!\n";     if(arg)    {        printf("%s",(char *)arg);    }     pbuf_free(p);        q = pbuf_alloc(PBUF_TRANSPORT, strlen(reply)+1, PBUF_RAM);    if(!q)    {    	   printf("out of PBUF_RAM\n"); 	   return;    }     memset(q->payload, 0 , q->len);    memcpy(q->payload, reply, strlen(reply));    udp_sendto(upcb, q, addr, port);    pbuf_free(q); }  static char * st_buffer= "We get a data\n"; void UDP_Echo_Init(void) {     struct udp_pcb *udpecho_pcb;     /* 新建一个控制块*/           udpecho_pcb = udp_new();          /* 绑定端口号 */     udp_bind(udpecho_pcb, IP_ADDR_ANY, UDP_ECHO_PORT);          /* 注册接收数据回调函数 */     udp_recv(udpecho_pcb, udp_demo_callback, (void *)st_buffer); } 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!