STM32移植LWIP之客户端与服务端的数据传输
服务端:
1 //tcp_server_demo.h 2 3 #ifndef __TCP_SERVER_DEMO_H 4 #define __TCP_SERVER_DEMO_H 5 #include "sys.h" 6 #include "includes.h" 7 8 9 #define TCP_SERVER_RX_BUFSIZE 1460 //定义tcp server最大接收数据长度 10 #define TCP_SERVER_PORT 8087 //定义tcp server的端口 11 #define LWIP_SEND_DATA 0X80 //定义有数据发送 12 13 extern u8 tcp_server_recvbuf[TCP_SERVER_RX_BUFSIZE]; //TCP客户端接收数据缓冲区 14 extern u8 tcp_server_flag; //TCP服务器数据发送标志位 15 extern u8 recflag; 16 17 INT8U tcp_server_init(void); //TCP服务器初始化(创建TCP服务器线程) 18 #endif
1 //tcp_server_demo.c 2 3 #include "tcp_server_demo.h" 4 #include "lwip/opt.h" 5 #include "lwip_comm.h" 6 #include "led.h" 7 #include "lwip/lwip_sys.h" 8 #include "lwip/api.h" 9 #include "lcd.h" 10 #include "malloc.h" 11 #include "recorder.h" 12 13 u8 tcp_server_recvbuf[TCP_SERVER_RX_BUFSIZE]; //TCP客户端接收数据缓冲区 14 u8 *tcp_server_sendbuf; 15 u8 recflag=0; 16 17 18 u8 receive_flag = 0; 19 20 21 22 //TCP客户端任务 任务优先级最高! 23 #define TCPSERVER_PRIO 6 24 //任务堆栈大小 25 #define TCPSERVER_STK_SIZE 300 26 //任务堆栈 27 OS_STK TCPSERVER_TASK_STK[TCPSERVER_STK_SIZE]; 28 29 30 31 /*服务器线程任务*/ 32 void my_tcp_server_thread(void *arg) 33 { 34 OS_CPU_SR cpu_sr; 35 36 struct pbuf *q; //创建pbuf 数据包 用于接收数据 37 u32 data_len = 0; //已经储存的数据长度 38 err_t err,recv_err; //创建异常标志 39 u8 remot_addr[4]; //创建一个客户机IP存储数组 40 struct netconn *conn, *newconn; //netconn任务块 LWIP会根据TCP还是UDP自动分配合适的消息邮箱 41 static ip_addr_t ipaddr; //创建一个存取ip地址的结构体 42 static u16_t port; //端口号 43 u8 i; 44 u8 re=0; 45 tcp_server_sendbuf=mymalloc(SRAMEX,SAI_RX_DMA_BUF_SIZE); 46 47 for(i=0;i<SAI_RX_FIFO_SIZE;i++) 48 { 49 sairecfifobuf2[i]=mymalloc(SRAMEX,SAI_RX_DMA_BUF_SIZE);//SAI接收FIFO内存申请 50 if(sairecfifobuf2[i]==NULL)break; //申请失败 51 } 52 if(!tcp_server_sendbuf||i!=SAI_RX_FIFO_SIZE) re=1; 53 while(re); 54 LWIP_UNUSED_ARG(arg); //让LWIP知道这个参数没使用 55 56 conn = netconn_new(NETCONN_TCP); //创建一个新TCP链接 57 netconn_bind(conn,IP_ADDR_ANY,TCP_SERVER_PORT); //绑定端口 8087号端口 58 netconn_listen(conn); //将conn置为监听状态 59 conn->recv_timeout = 10; //禁止阻塞线程 等待10ms 如果不等待,由于netconn_recv函数的使用 会阻塞线程 60 while(1) 61 { 62 err = netconn_accept(conn,&newconn); //获得一个新连接 63 if(err==ERR_OK) 64 { 65 newconn->recv_timeout = 10; //获取连接成功 newconn禁止阻塞线程 等待10ms 66 67 struct netbuf *recvbuf; //创建一个netbuf格式的recvbuf 因为LWIP接收到数据包后会将数据封装在一个 netbuf 中等待应用程序处理 68 69 netconn_getaddr(newconn,&ipaddr,&port,0); //获取newconn连接的 客户机IP地址和端口号 并存在ipaddr和port中 70 71 remot_addr[3] = (uint8_t)(ipaddr.addr >> 24); //远端ip复制到remot_addr 72 remot_addr[2] = (uint8_t)(ipaddr.addr>> 16); 73 remot_addr[1] = (uint8_t)(ipaddr.addr >> 8); 74 remot_addr[0] = (uint8_t)(ipaddr.addr); 75 76 u8 *tbuf; //使用LCD需要 77 tbuf=mymalloc(SRAMIN,200); //申请内存 78 POINT_COLOR = BLUE; 79 sprintf((char*)tbuf,"Client IP:%d.%d.%d.%d",remot_addr[0],remot_addr[1],remot_addr[2],remot_addr[3]); //显示客户端IP 80 LCD_ShowString(30,170,210,16,16,tbuf); 81 POINT_COLOR = RED; 82 sprintf((char*)tbuf,"Local Port:%d",port); //客户端端口号 83 LCD_ShowString(30,190,210,16,16,tbuf); 84 myfree(SRAMIN,tbuf); //一定要释放内存否则会卡死 85 while(1) 86 { 87 88 //数据发送函数 89 //数据发送完毕后终止循环,一定使用NOCOPY模式!!! 90 91 wav_buffill(tcp_server_sendbuf); //将发送FIFO中的数据填充到tcp_server_sendbuf中 92 while(netconn_write(newconn,tcp_server_sendbuf,1460,NETCONN_NOCOPY)); //将tcp_server_sendbuf中的数据发送出去 93 OSTimeDlyHMSM(0,0,0,20); 94 95 96 97 //OSTimeDlyHMSM(0,0,0,100); //系统延时50ms 98 99 //数据接收函数 100 if((recv_err =netconn_recv(newconn,&recvbuf) ) == ERR_OK) //判断是否收到数据 101 { 102 OS_ENTER_CRITICAL(); //关中断 103 104 memset(tcp_server_recvbuf,0,TCP_SERVER_RX_BUFSIZE); //数据接收缓冲区清零 105 106 for(q = recvbuf->p;q!=NULL;q=q->next) //遍历完整个pbuf链表 107 { 108 109 110 if(q->len > (TCP_SERVER_RX_BUFSIZE-data_len)) //判断要拷贝到TCP_SERVER_RX_BUFSIZE中的数据是否大于TCP_SERVER_RX_BUFSIZE的剩余空间,如果大于的话就只拷贝TCP_SERVER_RX_BUFSIZE中剩余长度的数据 111 memcpy(tcp_server_recvbuf+data_len,q->payload,(TCP_SERVER_RX_BUFSIZE-data_len));//拷贝数据 112 else 113 memcpy(tcp_server_recvbuf+data_len,q->payload,q->len); 114 115 data_len += q->len; 116 117 if(data_len > TCP_SERVER_RX_BUFSIZE) 118 break; //超出TCP客户端接收数组,跳出 119 } 120 rec_sai_fifo_write2(tcp_server_recvbuf); //将接收buf中的数据写入接收FIFO中 121 recflag++; 122 123 OS_EXIT_CRITICAL(); //开中断 124 data_len = 0; //复制完成后data_len要清零 125 netbuf_delete(recvbuf); //删除recvbuf空间 否则会内存泄露 126 } 127 128 129 else if(recv_err == ERR_CLSD) //如果收到关闭连接的通知 130 { 131 netconn_close(newconn); //关闭newconn服务端 132 netconn_delete(newconn); //删除服务端 否则会内存泄露 133 LCD_ShowString(30,170,210,16,16," "); 134 LCD_ShowString(30,190,210,16,16,"Connect closed "); 135 break; 136 } 137 } 138 } 139 } 140 } 141 142 143 144 145 146 //创建TCP服务器线程 147 //返回值:0 TCP服务器创建成功 148 // 其他 TCP服务器创建失败 149 INT8U tcp_server_init(void) 150 { 151 INT8U res; 152 OS_CPU_SR cpu_sr; 153 154 OS_ENTER_CRITICAL(); //关中断 155 res = OSTaskCreate(my_tcp_server_thread,(void*)0,(OS_STK*)&TCPSERVER_TASK_STK[TCPSERVER_STK_SIZE-1],TCPSERVER_PRIO); //创建TCP服务器线程 156 OS_EXIT_CRITICAL(); //开中断 157 158 return res; 159 }
客户端:
1 //tcp_client_demo.h 2 3 #ifndef __TCP_CLIENT_DEMO_H 4 #define __TCP_CLIENT_DEMO_H 5 #include "sys.h" 6 #include "includes.h" 7 8 9 10 #define TCP_CLIENT_RX_BUFSIZE 1460 //接收缓冲区长度 11 #define REMOTE_PORT 8087 //定义远端主机的IP地址 12 #define LWIP_SEND_DATA 0X80 //定义有数据发送 13 14 15 extern u8 tcp_client_recvbuf[TCP_CLIENT_RX_BUFSIZE]; //TCP客户端接收数据缓冲区 16 extern u8 tcp_client_flag; //TCP客户端数据发送标志位 17 extern u8 recflag; 18 19 INT8U tcp_client_init(void); //tcp客户端初始化(创建tcp客户端线程) 20 #endif
1 //tcp_client_demo.c 2 3 #include "t" 4 #include "lwip/opt.h" 5 #include "lwip_comm.h" 6 #include "lwip/lwip_sys.h" 7 #include "lwip/api.h" 8 #include "includes.h" 9 #include "key.h" 10 #include "malloc.h" 11 #include "lcd.h" 12 #include "recorder.h" 13 14 struct netconn *tcp_clientconn; //TCP CLIENT网络连接结构体 15 16 u8 tcp_client_recvbuf[TCP_CLIENT_RX_BUFSIZE]; //TCP客户端接收数据缓冲区 17 18 u8 *tcp_Client_sendbuf; 19 u8 recflag=0; 20 21 22 23 //TCP客户端任务 24 #define TCPCLIENT_PRIO 6 25 //任务堆栈大小 26 #define TCPCLIENT_STK_SIZE 300 27 //任务堆栈 28 OS_STK TCPCLIENT_TASK_STK[TCPCLIENT_STK_SIZE]; 29 30 void my_tcp_client_thread(void *arg) 31 { 32 OS_CPU_SR cpu_sr; 33 34 u32 data_len = 0; //已接收数据长度 35 struct pbuf *q; //定义一个数据包来存储数据 36 err_t err,recv_err; //标志位 37 38 static ip_addr_t server_ipaddr,loca_ipaddr; //服务器IP 本地IP 39 40 static u16_t server_port,loca_port; //服务器端口 本地端口号 41 u8 server_ip[4]; 42 43 u8 i; 44 u8 re=0; 45 tcp_Client_sendbuf=mymalloc(SRAMEX,SAI_RX_DMA_BUF_SIZE); 46 47 for(i=0;i<SAI_RX_FIFO_SIZE;i++) 48 { 49 sairecfifobuf2[i]=mymalloc(SRAMEX,SAI_RX_DMA_BUF_SIZE);//SAI接收FIFO内存申请 50 if(sairecfifobuf2[i]==NULL)break; //申请失败 51 } 52 if(!tcp_Client_sendbuf||i!=SAI_RX_FIFO_SIZE) re=1; 53 while(re); 54 55 56 LWIP_UNUSED_ARG(arg); //告诉LWIP这个参数没用 57 58 server_port = REMOTE_PORT; //服务器端口为 8087 59 60 IP4_ADDR(&server_ipaddr, lwipdev.remoteip[0],lwipdev.remoteip[1], lwipdev.remoteip[2],lwipdev.remoteip[3]); //设置IPV4的地址即服务器地址为192.198.1.100 61 62 server_ip[0] = lwipdev.remoteip[0]; 63 server_ip[1] = lwipdev.remoteip[1]; 64 server_ip[2] = lwipdev.remoteip[2]; 65 server_ip[3] = lwipdev.remoteip[3]; 66 67 while (1) 68 { 69 tcp_clientconn = netconn_new(NETCONN_TCP); //创建一个TCP链接 70 71 err = netconn_connect(tcp_clientconn,&server_ipaddr,server_port); //一直连接服务器 72 73 if(err != ERR_OK) 74 netconn_delete(tcp_clientconn); //返回值不等于ERR_OK,删除tcp_clientconn连接 75 else if (err == ERR_OK) //已经连接上了 处理新连接的数据 76 { 77 struct netbuf *recvbuf; //定义netbuf数据包 78 tcp_clientconn->recv_timeout = 10; // 延迟10ms禁止线程阻塞 79 netconn_getaddr(tcp_clientconn,&loca_ipaddr,&loca_port,1); //获取本地IP主机IP地址和端口号 80 81 82 u8 *tbuf; //使用LCD需要 83 tbuf=mymalloc(SRAMIN,200); //申请内存 84 POINT_COLOR = BLUE; 85 sprintf((char*)tbuf,"Server IP:%d.%d.%d.%d",server_ip[0],server_ip[1],server_ip[2],server_ip[3]); //显示服务器IP 86 LCD_ShowString(30,170,210,16,16,tbuf); 87 sprintf((char*)tbuf,"Local Port:%d",loca_port); //本地端口号 88 LCD_ShowString(30,190,210,16,16,tbuf); 89 myfree(SRAMIN,tbuf); //一定要释放内存否则会卡死 90 91 while(1) 92 { 93 wav_buffill(tcp_Client_sendbuf); 94 while(netconn_write(tcp_clientconn ,tcp_client_recvbuf,1460,NETCONN_COPY)); 95 96 OSTimeDlyHMSM(0,0,0,20); 97 98 99 100 if((recv_err = netconn_recv(tcp_clientconn,&recvbuf)) == ERR_OK) //接收到数据 101 { 102 OS_ENTER_CRITICAL(); //关中断 103 memset(tcp_client_recvbuf,0,TCP_CLIENT_RX_BUFSIZE); //数据接收缓冲区清零 104 105 for(q=recvbuf->p;q!=NULL;q=q->next) //遍历完整个pbuf链表 106 { 107 if(q->len > (TCP_CLIENT_RX_BUFSIZE-data_len)) 108 memcpy(tcp_client_recvbuf+data_len,q->payload,(TCP_CLIENT_RX_BUFSIZE-data_len));//判断要拷贝到TCP_CLIENT_RX_BUFSIZE中的数据是否大于TCP_CLIENT_RX_BUFSIZE的剩余空间,如果大于的话就只拷贝TCP_CLIENT_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据 109 else 110 memcpy(tcp_client_recvbuf+data_len,q->payload,q->len); 111 112 data_len += q->len; // 113 114 if(data_len > TCP_CLIENT_RX_BUFSIZE) 115 break; //超出TCP客户端接收数组,跳出 116 } 117 rec_sai_fifo_write2(tcp_client_recvbuf); 118 recflag++; 119 120 OS_EXIT_CRITICAL(); //开中断 121 122 123 data_len=0; //复制完成后data_len要清零。 124 netbuf_delete(recvbuf); 125 } 126 else if(recv_err == ERR_CLSD) //关闭连接 127 { 128 netconn_close(tcp_clientconn); 129 netconn_delete(tcp_clientconn); 130 LCD_ShowString(30,170,210,16,16," "); 131 LCD_ShowString(30,190,210,16,16,"Connect closed "); 132 break; 133 } 134 } 135 } 136 } 137 138 } 139 140 141 //创建TCP客户端线程 142 //返回值:0 TCP客户端创建成功 143 // 其他 TCP客户端创建失败 144 INT8U tcp_client_init(void) 145 { 146 INT8U res; 147 OS_CPU_SR cpu_sr; 148 149 OS_ENTER_CRITICAL(); //关中断 150 res = OSTaskCreate(my_tcp_client_thread,(void*)0,(OS_STK*)&TCPCLIENT_TASK_STK[TCPCLIENT_STK_SIZE-1],TCPCLIENT_PRIO); //创建TCP客户端线程 151 OS_EXIT_CRITICAL(); //开中断 152 153 return res; 154 }