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 }