LWIP裸机环境下实现TCP与UDP通讯
前面移植了LWIP,并且简单的实用了DHCP的功能,今天来使用一下实际的数据通讯的功能
首先是实现TCP客户端,我先上代码
#ifndef __TCP_CLIENT_H_ #define __TCP_CLIENT_H_ #include "network.h"//连接状态 enum tcp_client_states {ES_NONE = 0, ES_RECEIVED, //接收到了数据ES_CLOSING //连接关闭 };//TCP服务器状态 struct tcp_client_state {u8_t state; };#define LWIP_CLIENT_BUF 200 //TCP链接缓存extern u8 lwip_client_buf[LWIP_CLIENT_BUF]; //定义用来发送和接收数据的缓存extern u8 lwip_tcp_client_flag; //用于定义lwip tcp client状态//客户端成功连接到远程主机时调用 err_t Tcp_Client_Connect(void *arg,struct tcp_pcb *tpcb,err_t err);//连接轮询时将要调用的函数 err_t Tcp_Client_Poll(void *arg, struct tcp_pcb *tpcb);//用于连接远程主机 void Tcp_Client_Connect_Remotehost(void);//客户端接收到数据之后将要调用的函数 err_t Tcp_Client_Recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);//关闭连接 void Tcp_Client_Close(struct tcp_pcb *tpcb, struct tcp_client_state* ts);//初始化TCP客户端 void Tcp_Client_Init(void);#endif
#include "tcp_client.h"u8 lwip_tcp_client_flag; //用于定义lwip tcp client状态//定义一个TCP的协议控制块 struct tcp_pcb* tcp_client_pcb; //链接的自动回应信息 static const char* respond = "tcp_client connect success\r\n";u8 lwip_client_buf[LWIP_CLIENT_BUF]; //定义用来发送和接收数据的缓存//客户端成功连接到远程主机时调用 err_t Tcp_Client_Connect(void *arg,struct tcp_pcb *tpcb,err_t err) {struct tcp_client_state* ts;ts = arg; ts->state = ES_RECEIVED; //可以开始接收数据了lwip_tcp_client_flag |= LWIP_CONNECTED; //标记连接成功了tcp_write(tpcb,respond,strlen(respond),1); //回应信息 return ERR_OK; }//连接轮询时将要调用的函数 err_t Tcp_Client_Poll(void *arg, struct tcp_pcb *tpcb) {err_t ret_err;struct tcp_client_state* ts;ts = arg; // lwip_log("tcp_client_polling!\r\n");if(ts!=NULL)//连接处于空闲可以发送数据 { if((lwip_tcp_client_flag&LWIP_SEND_DATA)==LWIP_SEND_DATA){tcp_write(tpcb,lwip_client_buf,strlen((char *)lwip_client_buf),1);//发送数据lwip_tcp_client_flag &=~LWIP_SEND_DATA; //清除发送数据的标志 }}else{tcp_abort(tpcb);ret_err = ERR_ABRT;}return ret_err; }//用于连接远程主机 void Tcp_Client_Connect_Remotehost(void) {//记住如果此处需要频繁重连的时候记得先关闭已经申请的tcb//最好将tcb换成全局变量 // Tcp_Client_Close(); Tcp_Client_Init(); }//客户端接收到数据之后将要调用的函数 err_t Tcp_Client_Recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {err_t ret_err;struct tcp_client_state* ts;ts = arg; //TCP PCB状态if(p==NULL){ ts->state = ES_CLOSING; //连接关闭了 Tcp_Client_Close(tpcb,ts);lwip_tcp_client_flag &=~ LWIP_CONNECTED; //清除连接标志 }else if(err!=ERR_OK){ //位置错误释放pbufif(p!=NULL){pbuf_free(p);}ret_err = err; //得到错误 }else if(ts->state==ES_RECEIVED){//连接收到了新的数据// printf("服务器新接收的数据:%s\r\n",p->payload);if((p->tot_len)>=LWIP_CLIENT_BUF){ //如果收的的数据大于缓存((char*)p->payload)[199] = 0; memcpy(lwip_client_buf,p->payload,200);}else{ memcpy(lwip_client_buf,p->payload,p->tot_len);lwip_client_buf[p->tot_len] = 0; }lwip_tcp_client_flag |= LWIP_NEW_DATA; //收到了新的数据tcp_recved(tpcb, p->tot_len); //用于获取接收数据的长度, 表示可以获取更多的数据 pbuf_free(p); //释放内存ret_err = ERR_OK;}else if(ts->state==ES_CLOSING)//服务器关闭了 { tcp_recved(tpcb, p->tot_len); //远程端口关闭两次,垃圾数据 pbuf_free(p);ret_err = ERR_OK;}else{ //其他未知状态tcp_recved(tpcb, p->tot_len);pbuf_free(p);ret_err = ERR_OK;}return ret_err;}//关闭连接 void Tcp_Client_Close(struct tcp_pcb *tpcb, struct tcp_client_state* ts) {tcp_arg(tcp_client_pcb, NULL); tcp_recv(tcp_client_pcb, NULL);tcp_poll(tcp_client_pcb, NULL, 0); if(ts!=NULL){mem_free(ts);}tcp_close(tpcb); }//指定连接的客户端为1300端口 #define TCP_CLIENT_PORT 1300//初始化TCP客户端 void Tcp_Client_Init(void) {struct tcp_client_state* ts;ip_addr_t ipaddr;IP4_ADDR(&ipaddr, 192, 168, 1, 101); tcp_client_pcb = tcp_new(); //新建一个PCBif(tcp_client_pcb!=NULL){ ts = mem_malloc(sizeof(struct tcp_client_state)); //申请内存tcp_arg(tcp_client_pcb, ts); //将程序的协议控制块的状态传递给多有的回调函数//设定TCP的回调函数tcp_connect(tcp_client_pcb,&ipaddr,TCP_CLIENT_PORT,Tcp_Client_Connect);tcp_recv(tcp_client_pcb, Tcp_Client_Recv); //指定连接接收到新的数据之后将要调用的回调函数tcp_poll(tcp_client_pcb, Tcp_Client_Poll, 0); //指定轮询时将要调用的回调函数 } }
我们可以看到,在tcp客户端初始化的时候我们使用了回调函数技术将接收数据和轮询数据的函数添加到了网络的底层轮转中,还要指定链接的端口和ip,但是不需要指定本地端口
同时,我们还在在程序主循环中不停地处理网络事件(因为没有操作系统)
//LWIP查询 void LWIP_Polling(void) {if(timer_expired(&input_time,5)) //接收包,周期处理函数 {ethernetif_input(&enc28j60_netif); }if(timer_expired(&last_tcp_time,TCP_TMR_INTERVAL/CLOCKTICKS_PER_MS))//TCP处理定时器处理函数 {tcp_tmr();}if(timer_expired(&last_arp_time,ARP_TMR_INTERVAL/CLOCKTICKS_PER_MS))//ARP处理定时器 {etharp_tmr();}if(timer_expired(&last_ipreass_time,IP_TMR_INTERVAL/CLOCKTICKS_PER_MS))//IP重新组装定时器 { ip_reass_tmr();} }
这样,完整的TCP通讯链路就能建成了,数据的使用这样
if((lwip_tcp_client_flag&LWIP_CONNECTED)==LWIP_CONNECTED){LCD_ShowString(0,24,240,320,(u8*)"TCP CLIENT Connect ",LCD_BLACK);if(keyValue == KEY_RIGHT){t_client_cnt++;sprintf((char*)lwip_client_buf,"tcp_client send %d\r\n",t_client_cnt); LCD_ShowString(18,48,240,320,(u8*)lwip_client_buf,LCD_BLACK);//显示当前发送数据lwip_tcp_client_flag |= LWIP_SEND_DATA; //标记有数据需要发送keyValue = 0;}}else{ // Tcp_Client_Connect_Remotehost();//没有连接上,此时处于TCP客户端模式,则尝试重新连接 }if((lwip_tcp_client_flag&LWIP_NEW_DATA)==LWIP_NEW_DATA){LCD_ShowString(18,36,240,320,(u8*)lwip_client_buf,LCD_BLACK);lwip_tcp_client_flag &=~LWIP_NEW_DATA; //清除接受数据的标志}
同理,TCP服务器的流程也差不多,但是多了一个东西,tcp服务器要监听本地某一个特定端口,使用如下
#include "tcp_service.h"struct tcp_pcb* tcp_server_pcb;//定义一个TCP的协议控制块static const char* respond = "tcp_service connect ok!\r\n";u8 lwip_tcp_service_flag; //用于定义lwip tcp client状态 u8 lwip_service_buf[LWIP_SERCER_BUF]; //定义用来发送和接收数据的缓存//初始化LWIP服务器 void Init_TCP_Server(void) {err_t err; //LWIP错误信息tcp_server_pcb = tcp_new(); //新建一个TCP协议控制块if(tcp_server_pcb!=NULL){err = tcp_bind(tcp_server_pcb,IP_ADDR_ANY,TCP_SERVER_PORT);//绑定本地所有IP地址和端口号 作为服务器不需要知道客户端的IPif(err==ERR_OK)//成功绑定 {tcp_server_pcb = tcp_listen(tcp_server_pcb); //开始监听端口tcp_accept(tcp_server_pcb,Tcp_Server_Accept); //指定监听状态的连接联通之后将要调用的回调函数 }}}//服务器连接成功后将要调用的函数 err_t Tcp_Server_Accept(void *arg, struct tcp_pcb *newpcb, err_t err) {err_t ret_err;struct tcp_server_state* ts;ts = mem_malloc(sizeof(struct tcp_server_state)); //申请内存if(ts!=NULL){ts->state = ES_SERVER_RECEIVED; //可以接收数据了lwip_tcp_service_flag |= LWIP_CONNECTED; //已经连接上了tcp_write(newpcb,respond,strlen(respond),1); //回应信息 tcp_arg(newpcb, ts); //将程序的协议控制块的状态传递给多有的回调函数 tcp_recv(newpcb, Tcp_Server_Recv); //指定连接接收到新的数据之后将要调用的回调函数tcp_err(newpcb, Tcp_Server_Error); //指定连接出错将要调用的函数tcp_poll(newpcb, Tcp_Server_Poll, 0); //指定轮询时将要调用的回调函数ret_err = ERR_OK;}else{ret_err = ERR_MEM;}return ret_err;}//连接轮询时将要调用的函数 err_t Tcp_Server_Poll(void *arg, struct tcp_pcb *tpcb) {err_t ret_err;struct tcp_server_state* ts;ts = arg;if(ts!=NULL){ //连接处于空闲可以发送数据if((lwip_tcp_service_flag&LWIP_SEND_DATA)==LWIP_SEND_DATA){tcp_write(tpcb,lwip_service_buf,strlen((char *)lwip_service_buf),1);//发送数据lwip_tcp_service_flag &=~LWIP_SEND_DATA; //清除发送数据的标志 }}else{tcp_abort(tpcb);ret_err = ERR_ABRT;}return ret_err; }//服务器接收到数据之后将要调用的函数 err_t Tcp_Server_Recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {err_t ret_err;struct tcp_server_state* ts;ts = arg; //TCP PCB状态if(p==NULL){ ts->state = ES_SERVER_CLOSING; //连接关闭了 Tcp_Server_Close(tpcb,ts);lwip_tcp_service_flag &=~ LWIP_CONNECTED; //清除连接标志 }else if(err!=ERR_OK){ //未知错误,释放pbufif(p!=NULL){pbuf_free(p);}ret_err = err; //得到错误 }else if(ts->state==ES_SERVER_RECEIVED){//连接收到了新的数据if((p->tot_len)>=LWIP_SERCER_BUF){ //如果收的的数据大于缓存((char*)p->payload)[199] = 0; memcpy(lwip_service_buf,p->payload,200);}else{ memcpy(lwip_service_buf,p->payload,p->tot_len);lwip_service_buf[p->tot_len] = 0; }lwip_tcp_service_flag |= LWIP_NEW_DATA; //收到了新的数据 tcp_recved(tpcb, p->tot_len); //用于获取接收数据的长度, 通知LWIP已经读取了数据,可以获取更多的数据pbuf_free(p); //释放内存ret_err = ERR_OK;}else if(ts->state==ES_SERVER_CLOSING){ //服务器关闭了tcp_recved(tpcb, p->tot_len); //远程端口关闭两次,垃圾数据 pbuf_free(p);ret_err = ERR_OK;}else{ //其他未知状态tcp_recved(tpcb, p->tot_len);pbuf_free(p);ret_err = ERR_OK;}return ret_err;}//连接出错将要调用的函数 void Tcp_Server_Error(void *arg,err_t err) {struct tcp_server_state* ts;ts = arg;if(ts!=NULL){mem_free(ts);} }//关闭连接 void Tcp_Server_Close(struct tcp_pcb *tpcb, struct tcp_server_state* ts) {if(ts!=NULL){mem_free(ts);}tcp_close(tpcb); }
可以看到上面的代码多了一个bind的过程
剩下的就是udp通讯了,在之前tcp的源码里面能看到,发送数据的时候不需要专门去做发送函数,指定一个标志位就行了,在轮转的时候程序会自动把数据发送出去,当使用UDP的时候就不行了,因为TCP是面向链接的,而UDP本身就是无连接的,UDP的是使用源码如下
#include "udp_send.h"//该文件即可以接受也可以发送数据 //都是用1500端口进行操作 u8 lwip_udp_send_buf[LWIP_UDP_SEND_BUF]; //定义用来发送和接收数据的缓存 u8 lwip_udp_send_flag; //用于定义lwip tcp client状态struct udp_pcb* udp_client_pcb;//定义一个UDP的协议控制块 struct pbuf * ubuf_client;//接收到数据包将要调用的函数 void udp_client_rev(void* arg,struct udp_pcb* upcb,struct pbuf* p,struct ip_addr*addr ,u16_t port) {if(p!=NULL){if((p->tot_len)>=LWIP_UDP_SEND_BUF){ //如果收的的数据大于缓存((char*)p->payload)[199] = 0; memcpy(lwip_udp_send_buf,p->payload,200);}else{ memcpy(lwip_udp_send_buf,p->payload,p->tot_len);lwip_udp_send_buf[p->tot_len] = 0; }lwip_udp_send_flag |= LWIP_NEW_DATA; //收到了新的数据 pbuf_free(p);} }//发送数据 void udp_client_send_data(void) {err_t err;if((lwip_udp_send_flag&LWIP_SEND_DATA)==LWIP_SEND_DATA){ubuf_client = pbuf_alloc(PBUF_TRANSPORT, strlen((char *)lwip_udp_send_buf), PBUF_RAM); //为发送包分配内存ubuf_client->payload = lwip_udp_send_buf;err=udp_send(udp_client_pcb,ubuf_client);//发送数据if(err!=ERR_OK){//lwip_log("UDP SERVER发送数据失败!"); }lwip_udp_send_flag &=~LWIP_SEND_DATA; //清除发送数据的标志 pbuf_free(ubuf_client);} }//初始化UDP客户端 void Init_UDP_Client(void) {//struct ip_addr* ipaddr; ip_addr_t ipaddr;IP4_ADDR(&ipaddr, 192, 168, 1, 101); //设置本地ip地址udp_client_pcb = udp_new(); //新建一个UDP协议控制块if(udp_client_pcb!=NULL){udp_bind(udp_client_pcb,IP_ADDR_ANY,UDP_CLIENT_PORT); // udp_connect(udp_client_pcb,&ipaddr,UDP_CLIENT_PORT); //设置连接到远程主机udp_recv(udp_client_pcb,udp_client_rev,NULL); //指定收到数据包时的回调函数 } }
这是一个UDP的客户端,在初始化的时候指明了目的主机的地址和端口号,连接到目的主机上
接下来是一个UDP的服务器
#include "udp_recv.h"struct udp_pcb* udp_server_pcb;//定义一个UDP的协议控制块 struct pbuf * ubuf;u8 lwip_udp_recv_buf[LWIP_UDP_RECV_BUF]; //定义用来发送和接收数据的缓存 u8 lwip_udp_recv_flag; //用于定义lwip tcp client状态//接收到数据包将要调用的函数 void Udp_Server_Recv(void* arg,struct udp_pcb* upcb,struct pbuf* p,struct ip_addr*addr ,u16_t port) {if(p!=NULL){if((p->tot_len)>=LWIP_UDP_RECV_BUF){ //如果收的的数据大于缓存((char*)p->payload)[199] = 0; memcpy(lwip_udp_recv_buf,p->payload,200);}else{ memcpy(lwip_udp_recv_buf,p->payload,p->tot_len);lwip_udp_recv_buf[p->tot_len] = 0; }lwip_udp_recv_flag |= LWIP_NEW_DATA; //收到了新的数据udp_server_pcb->remote_ip = *addr; //记录远程主机的IP和端口号udp_server_pcb->remote_port = port;pbuf_free(p);} }//发送数据 void Udp_Server_Send_Data(void) {err_t err;if((lwip_udp_recv_flag&LWIP_SEND_DATA)==LWIP_SEND_DATA){ubuf = pbuf_alloc(PBUF_TRANSPORT, strlen((char *)lwip_udp_recv_buf), PBUF_RAM); ubuf->payload = lwip_udp_recv_buf;err=udp_send(udp_server_pcb,ubuf);//发送数据if(err!=ERR_OK){//do something }lwip_udp_recv_flag &=~LWIP_SEND_DATA; //清除发送数据的标志 pbuf_free(ubuf);} }//初始化UDP服务器 void Init_UDP_Server(void) {udp_server_pcb = udp_new(); //新建一个UDP协议控制块if(udp_server_pcb!=NULL){udp_bind(udp_server_pcb,IP_ADDR_ANY,UDP_RECV_PORT); //监听一个UDP端口udp_recv(udp_server_pcb,Udp_Server_Recv,NULL); //指定收到数据包时的回调函数 } }
可以看到,UDP的服务器在使用的时候没有主动去连接那个IP,他只是自己绑定了自己的某个端口,算是客户端和服务器编程的两种差异
给一个使用文件
#include "mainInclude.h"#include "lwip/init.h" #include "lwip/ip.h" #include "lwip/dhcp.h" #include "lwip/tcp_impl.h" #include "lwip/ip_frag.h" #include "lwip/dns.h" #include "netif/etharp.h" #include "netif/ethernetif.h" #include "arch/sys_arch.h"#define CLOCKTICKS_PER_MS 10 //定义时钟节拍static ip_addr_t ipaddr, netmask, gw; //定义IP地址 struct netif enc28j60_netif; //定义网络接口 u32_t input_time; u32_t last_arp_time; u32_t last_tcp_time; u32_t last_ipreass_time;u32_t last_dhcp_fine_time; u32_t last_dhcp_coarse_time; u32 dhcp_ip=0;//LWIP查询 void LWIP_Polling(void) {if(timer_expired(&input_time,5)) //接收包,周期处理函数 {ethernetif_input(&enc28j60_netif); }if(timer_expired(&last_tcp_time,TCP_TMR_INTERVAL/CLOCKTICKS_PER_MS))//TCP处理定时器处理函数 {tcp_tmr();}if(timer_expired(&last_arp_time,ARP_TMR_INTERVAL/CLOCKTICKS_PER_MS))//ARP处理定时器 {etharp_tmr();}if(timer_expired(&last_ipreass_time,IP_TMR_INTERVAL/CLOCKTICKS_PER_MS))//IP重新组装定时器 { ip_reass_tmr();} }int main(void) {u8 t_client_cnt = 0;u8 t_server_cnt = 0;u8 t_send_cnt = 0;u8 t_recv_cnt = 0;NVIC_Group_Init();//系统默认中断分组Debug_Serial_Init(115200);Delay_Init();Led_Init();Key_Exti_Init();LCD_Init();LCD_Clear(LCD_BLACK);IP4_ADDR(&ipaddr, 192, 168, 1, 110); //设置本地ip地址IP4_ADDR(&gw, 192, 168, 1, 1); //网关IP4_ADDR(&netmask, 255, 255, 255, 0); //子网掩码 //初始化LWIP定时器 init_lwip_timer(); //初始化LWIP协议栈,执行检查用户所有可配置的值,初始化所有的模块 lwip_init();//添加网络接口while((netif_add(&enc28j60_netif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input)==NULL)){LCD_ShowString(0,0,240,320,(u8*)"ENC28J60 Init Failed ",LCD_BLACK);Delay_Ms(200);LCD_ShowString(0,0,240,320,(u8*)" ",LCD_BLACK);Delay_Ms(200);}LCD_ShowString(0,0,240,320,(u8*)"ENC28J60 Init OK ",LCD_BLACK);//注册默认的网络接口netif_set_default(&enc28j60_netif);//建立网络接口用于处理通信netif_set_up(&enc28j60_netif); Tcp_Client_Init();//初始化tcp客户端 LCD_ShowString(0,12,240,320,(u8*)"TCP CLIENT INIT ",LCD_BLACK);LCD_ShowString(0,24,240,320,(u8*)"TCP CLIENT Disconnect ",LCD_BLACK);LCD_ShowString(0,36,240,320,(u8*)"RX: ",LCD_BLACK);LCD_ShowString(0,48,240,320,(u8*)"TX: ",LCD_BLACK);Init_TCP_Server();LCD_ShowString(0,60,240,320,(u8*)"TCP SERVER INIT ",LCD_BLACK);LCD_ShowString(0,72,240,320,(u8*)"TCP SERVER Disconnect ",LCD_BLACK);LCD_ShowString(0,84,240,320,(u8*)"RX: ",LCD_BLACK);LCD_ShowString(0,96,240,320,(u8*)"TX: ",LCD_BLACK);Init_UDP_Client();LCD_ShowString(0,108,240,320,(u8*)"UDP SEND INIT ",LCD_BLACK);LCD_ShowString(0,120,240,320,(u8*)"RX: ",LCD_BLACK);LCD_ShowString(0,132,240,320,(u8*)"TX: ",LCD_BLACK);Init_UDP_Server();//初始化UDP接收端LCD_ShowString(0,144,240,320,(u8*)"UDP RECV INIT ",LCD_BLACK);LCD_ShowString(0,156,240,320,(u8*)"RX: ",LCD_BLACK);LCD_ShowString(0,168,240,320,(u8*)"TX: ",LCD_BLACK);while(1){LWIP_Polling();if((lwip_tcp_client_flag&LWIP_CONNECTED)==LWIP_CONNECTED){LCD_ShowString(0,24,240,320,(u8*)"TCP CLIENT Connect ",LCD_BLACK);if(keyValue == KEY_RIGHT){t_client_cnt++;sprintf((char*)lwip_client_buf,"tcp_client send %d\r\n",t_client_cnt); LCD_ShowString(18,48,240,320,(u8*)lwip_client_buf,LCD_BLACK);//显示当前发送数据lwip_tcp_client_flag |= LWIP_SEND_DATA; //标记有数据需要发送keyValue = 0;}}else{ // Tcp_Client_Connect_Remotehost();//没有连接上,此时处于TCP客户端模式,则尝试重新连接 }if((lwip_tcp_client_flag&LWIP_NEW_DATA)==LWIP_NEW_DATA){LCD_ShowString(18,36,240,320,(u8*)lwip_client_buf,LCD_BLACK);lwip_tcp_client_flag &=~LWIP_NEW_DATA; //清除接受数据的标志 }if((lwip_tcp_service_flag&LWIP_CONNECTED)==LWIP_CONNECTED){LCD_ShowString(0,72,240,320,(u8*)"TCP SERVER Connect ",LCD_BLACK);if(keyValue == KEY_LEFT){t_server_cnt++;sprintf((char*)lwip_service_buf,"tcp_service send %d\r\n",t_server_cnt); LCD_ShowString(18,96,240,320,(u8*)lwip_service_buf,LCD_BLACK);//显示当前发送数据lwip_tcp_service_flag |= LWIP_SEND_DATA; //标记有数据需要发送keyValue = 0;}}if((lwip_tcp_service_flag&LWIP_NEW_DATA)==LWIP_NEW_DATA){LCD_ShowString(18,84,240,320,(u8*)lwip_service_buf,LCD_BLACK);lwip_tcp_service_flag &=~LWIP_NEW_DATA; //清除接受数据的标志 }if(keyValue == KEY_UP){t_send_cnt++;sprintf((char*)lwip_udp_send_buf,"udp_send send %d\r\n",t_send_cnt); LCD_ShowString(18,132,240,320,(u8*)lwip_udp_send_buf,LCD_BLACK);//显示当前发送数据lwip_udp_send_flag |= LWIP_SEND_DATA; //标记有数据需要发送keyValue = 0;udp_client_send_data();}if((lwip_udp_send_flag&LWIP_NEW_DATA)==LWIP_NEW_DATA){LCD_ShowString(18,120,240,320,(u8*)lwip_udp_send_buf,LCD_BLACK);lwip_udp_send_flag &=~LWIP_NEW_DATA; //清除接受数据的标志 }if(keyValue == KEY_DOWN){t_recv_cnt++;sprintf((char*)lwip_udp_recv_buf,"udp_recv send %d\r\n",t_send_cnt); LCD_ShowString(18,168,240,320,(u8*)lwip_udp_recv_buf,LCD_BLACK);//显示当前发送数据lwip_udp_recv_flag |= LWIP_SEND_DATA; //标记有数据需要发送keyValue = 0;Udp_Server_Send_Data();}if((lwip_udp_recv_flag&LWIP_NEW_DATA)==LWIP_NEW_DATA){LCD_ShowString(18,156,240,320,(u8*)lwip_udp_recv_buf,LCD_BLACK);lwip_udp_recv_flag &=~LWIP_NEW_DATA; //清除接受数据的标志 }Delay_Ms(1);} }void USB_LP_CAN1_RX0_IRQHandler(void) {}void USBWakeUp_IRQHandler(void) { // EXTI->PR|=1<<18;//清除USB唤醒中断挂起位 }
完整的工程路径如下
http://download.csdn.net/detail/dengrengong/8555627
转载于:https://www.cnblogs.com/dengxiaojun/p/4385491.html
LWIP裸机环境下实现TCP与UDP通讯相关推荐
- LWIP裸机环境下实现TCP与UDP通讯(转)
源: LWIP裸机环境下实现TCP与UDP通讯
- EasyCVR国标GB28181协议接入下的TCP和UDP模式说明及差异
有用户在使用我们的平台时,经常会出现对于端口的疑问,同时也不了解端口的差别.今天我们来解释说明下EasyCVR平台关于国标GB28181协议接入下的TCP和UDP模式的说明及差异. 1.TCP与UDP ...
- android手机版tcp或者udp通讯测试工具,可以用于工业设备或者系统开发时间测试tcp或是udp连接通讯是否正常工作
TUtool 介绍 由于工作需要一款安卓的tcp udp测试工具,而市场里没有或者不好用,或者都是广告,现在个人开发者又不让发布应用了,小巧好用不收集用户信息的不收费没有广告的小工具只能自己用,哈哈. ...
- tcp通讯 怎么进行安全认证_西门子PLC在博图环境下进行TCP通讯详解
对于做工控设备的人员来说,精通各种通讯协议的使用是必不可少的,通讯协议就像语言一样,只有双方都约定好了协议之后,我才能知道你想做什么以及你需要什么,反之同理.这几天做了一个项目,是博图环境下使用西门子 ...
- tcp和udp通讯协议
转自:http://blog.csdn.net/li_ning_/article/details/52117463 TCP UDP TCP与UDP基本区别 1.基于连接与无连接 2.TCP要求 ...
- LwIP应用笔记(三):在RTOS环境下运行LwIP协议栈
前言 这篇文章是 LwIP应用笔记(二):无操作系统支持下的RAW API移植 的后续,以下所有内容都是建立在已经完成RAW API移植的前提下.本文可能不会太纠结于代码细节,因为本文的目标并不是演示 ...
- 弱网络环境下最优调度和优化传输层协议方案
一.背景 与有线网络通信相比,无线网络通信受环境影响比较大(例如高层建筑.用户移动.环境噪音.相对封闭环境等等),网络的服务质量相对来说不是非常稳定,导致用户经常会在弱信号的网络环境下通信.而当用户在 ...
- Windows下的TCP通信
刚好最近在做tcp.udp通信的实验就顺便写了这篇,方便以后查阅 文章目录 环境 步骤 流程图 源代码 环境 windows 10 visual studio2013 步骤 使用WSAStartup( ...
- EasyCVR国标GB28181协议接入时TCP和UDP模式的差异
有用户在使用我们的平台时,经常会出现对于端口的疑问,同时也不了解端口的差别.今天我们来解释说明下EasyCVR平台关于国标GB28181协议接入下的TCP和UDP模式的说明及差异. 1.TCP与UDP ...
最新文章
- 嵌入式Linux常用文件系统
- win7 命令行设置DNS,建立集测环境
- VTK:Kochanek样条用法实战
- 蓝牙BLE(协议栈、OSAL、蓝牙APP工具)
- Minimum spanning tree HDU - 6954
- webpack 3 零基础入门教程 #12 - 如何使用模块热替换 HMR 来处理 CSS
- 信息学奥赛一本通(1218:取石子游戏)
- Eclipse Windows环境配置
- vue+sortable实现表格拖拽
- 单机类似节奏大师游戏源码项目
- ubuntu退出mysql sql语句_Ubuntu 16.04安装、卸载mysql及怎么使用SQL常用操作语句
- 《图解算法》学习笔记之递归
- 显示器色域检测软件_摄影师:手机看图的甲方爸爸值得我换专业摄影显示器吗?...
- 春天樱花飘落flash源文件
- red hat linux没有库文件libiconv.so,libiconv库链接问题一则(备忘)
- 【嵌入式系统开发08】STM32F103C8T6搭建电路实现流水灯详解
- Code::Blocks安装和汉化包配置
- UTC时间转成北京时间
- 学习到第一个国庆的感想
- 考研初试考java的学校,2021考研初试科目:这些学校改成统考408!