阅读量: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); }