README_zh.md
1# 小凌派-RK2206开发板基础外设开发——wifi-tcp通信
2
3本示例将演示如何在小凌派-RK2206开发板上使用wifi进行tcp通信
4
5
6
7## WiFi ssid 和密码设置
8
9修改文件 ``device/soc/rockchip/rk2206/sdk_liteos/platform/network/config_network.c`` 中的SSID WiFi名称,PASSWORD WiFi密码 连接到与pc同一网络
10
11```c
12#define SSID "凌智电子"
13#define PASSWORD "88888888"
14```
15
16确认main文件 ``device/soc/rockchip/rk2206/sdk_liteos/platform/main/main.c`` wifi功能已开启
17
18```c
19ExternalTaskConfigNetwork();
20```
21
22### 查看小凌派获取到的IP地址和网关
23
24图如下所示:
25
26
27### 确认pc与小凌派在同一局域网,查看PC的IP地址和网关
28
29在控制台输入 ``ipconfig``
30图如下所示:
31
32网关都是 ``192.168.2.1``表示在同一局域网
33
34修改wifi_tcp例程中 服务地址及端口号后重新编译烧录程序
35
36```c
37#define OC_SERVER_IP "192.168.2.49" //pc IP地址 此地址为上一步查询到的地址每个人的地址可能不一样需要根据自己的修改
38#define SERVER_PORT 6666 //端口号
39```
40
41pc上打开两个网络调试工具一个客户端一个服务端,并设置IP地址和端口号
42
43
44查看log 等待小凌派的tcp客户端和服务端任务启动
45
46
47当小凌派tcp客户端和服务端启动后, 再用网络调试助手点击启动客户端和服务端
48
49
50然后就可以通过网络工具与小凌派通信了
51
52
53## 程序设计
54
55### API分析
56
57#### 头文件
58
59```c
60#include "lz_hardware.h"
61#include "config_network.h"
62#include "lwip/tcp.h"
63#include "lwip/ip_addr.h"
64#include "lwip/priv/tcp_priv.h"
65#include "lwip/stats.h"
66#include "lwip/inet_chksum.h"
67```
68
69#### socket()
70
71```c
72int socket(int domain, int type, int protocol);
73```
74
75**描述:**
76
77创建套接字
78**参数:**
79
80| 名字 | 描述 |
81| :------- | :------------------------------------------------ |
82| domai | 协议类型,一般为AF_INET |
83| type | socket类型 |
84| protocol | 用来指定socket所使用的传输协议编号,通常设为0即可 |
85
86**返回值:**
87
88返回大于0为成功,反之为失败
89
90#### bind()
91
92```c
93int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
94```
95
96**描述:**
97
98绑定地址端口号
99
100**参数:**
101
102| 名字 | 描述 |
103| :------ | :----------------------------------------------------------- |
104| sockfd | socket描述符 |
105| my_addr | 是一个指向包含有本机ip地址和端口号等信息的sockaddr类型的指针 |
106| addrlen | 常被设为sizeof(struct sockaddr) |
107
108**返回值:**
109
110返回大于0为成功,反之为失败
111
112#### connect()
113
114```c
115int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
116```
117
118**描述:**
119
120连接。
121
122**参数:**
123
124| 名字 | 描述 |
125| :-------- | :------------------------------- |
126| sockfd | 目的服务器的socket描述符 |
127| serv_addr | 包含目的机器ip地址和端口号的指针 |
128| addrlen | sizeof(struct sockaddr) |
129
130**返回值:**
131
132返回大于0为成功,反之为失败
133
134#### listen()
135
136```c
137int listen(int sockfd, int backlog);
138```
139
140**描述:**
141
142监听
143
144**参数:**
145
146| 名字 | 描述 |
147| :------ | :--------------------------------------------------------------- |
148| sockfd | socket()系统调用返回的socket描述符 |
149| backlog | 指定在请求队列中的最大请求数,进入的连接请求将在队列中等待accept |
150
151**返回值:**
152
153返回等于0为成功,反之为失败
154
155#### accept()
156
157```c
158int accept(int sockfd, void *addr, int addrlen);
159```
160
161**描述:**
162
163接受的一个连接
164
165**参数:**
166
167| 名字 | 描述 |
168| :------ | :------------------------------------------------------------------------------ |
169| sockfd | 是被监听的socket描述符 |
170| addr | 通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息 |
171| addrlen | sizeof(struct sockaddr_in) |
172
173**返回值:**
174
175如果没有错误产生,则accept()返回一个描述所接受包的SOCKET类型的值
176
177#### send()
178
179```c
180int send(int sockfd, const void *msg, int len, int flags);
181```
182
183**描述:**
184
185发送消息
186
187**参数:**
188
189| 名字 | 描述 |
190| :----- | :------------------------- |
191| sockfd | 用来传输数据的socket描述符 |
192| msg | 要发送数据的指针 |
193| len | 要发送的数据长度(字节) |
194| flags | 0 |
195
196**返回值:**
197
198发送成功返回发送字节数,失败返回值小于0
199
200#### recv()
201
202```c
203int recv(int sockfd, void *buf, int len, unsigned int flags);
204```
205
206**描述:**
207
208接收消息
209
210**参数:**
211
212| 名字 | 描述 |
213| :----- | :--------------------- |
214| sockfd | 接收数据的socket描述符 |
215| buf | 存放数据的缓冲区 |
216| len | 缓冲的长度(字节) |
217| flags | 0 |
218
219**返回值:**
220
221接收成功返回大于0,失败返回值小于0
222
223#### lwip_close()
224
225```c
226int lwip_close(int sockfd);
227```
228
229**描述:**
230
231关闭套接字
232
233**参数:**
234
235| 名字 | 描述 |
236| :----- | :------------- |
237| sockfd | 要关闭的套接字 |
238
239**返回值:**
240
241发送成功返回发送字节数,失败返回值小于0
242
243### 主要代码分析
244
245创建客户端任务 socket-->connect-->send-->recv-->lwip_close
246
247```c
248int wifi_client(void)
249{
250 int client_fd, ret;
251 struct sockaddr_in serv_addr;
252
253 while(1)
254 {
255 client_fd = socket(AF_INET, SOCK_STREAM, 0);//AF_INET:IPV4;SOCK_STREAM:TCP
256 if (client_fd < 0)
257 {
258 printf("create socket fail!\n");
259 return -1;
260 }
261
262 /*设置调用close(socket)后,仍可继续重用该socket。调用close(socket)一般不会立即关闭socket,而经历TIME_WAIT的过程。*/
263 int flag = 1;
264 ret = setsockopt(client_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int));
265 if (ret != 0) {
266 printf("[CommInitTcpServer]setsockopt fail, ret[%d]!\n", ret);
267 }
268
269 memset(&serv_addr, 0, sizeof(serv_addr));
270 serv_addr.sin_family = AF_INET;
271 serv_addr.sin_addr.s_addr = inet_addr(OC_SERVER_IP);
272 serv_addr.sin_port = htons(SERVER_PORT);
273 printf("[tcp client] connect:%d<%s:%d>\n",client_fd, inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
274
275
276 tcp_client_msg_handle(client_fd, (struct sockaddr*)&serv_addr);
277
278 LOS_Msleep(1000);
279 }
280}
281```
282
283连接服务端,并发送消息和接收消息
284
285```c
286void tcp_client_msg_handle(int fd, struct sockaddr* dst)
287{
288 int cnt = 0, count = 0;
289 while (connect(fd, dst, len) < 0)
290 {
291 printf("connect server failed...%d\n", ++count);
292 lwip_close(fd);
293 LOS_Msleep(5000);
294 fd = socket(AF_INET, SOCK_STREAM, 0); //AF_INET:IPV4;SOCK_STREAM:TCP
295 }
296
297 while (1)
298 {
299 char buf[BUFF_LEN];
300 sprintf(buf, "TCP TEST cilent send:%d", ++cnt);
301 count = send(fd, buf, strlen(buf), 0); //发送数据给server
302 // count = lwip_write(fd, buf, strlen(buf)); //发送数据给server
303 printf("------------------------------------------------------------\n");
304 printf("[tcp client] send:%s\n", buf);
305 printf("[tcp client] client sendto msg to server %d,waitting server respond msg!!!\n", count);
306 memset(buf, 0, BUFF_LEN);
307 count = recv(fd, buf, BUFF_LEN, 0); //接收来自server的信息
308 // count = lwip_read(fd, buf, BUFF_LEN); //接收来自server的信息
309 if(count == -1)
310 {
311 printf("[tcp client] recieve data fail!\n");
312 LOS_Msleep(3000);
313 break;
314 }
315 printf("[tcp client] rev:%s\n", buf);
316 }
317 lwip_close(fd);
318}
319```
320
321创建服务端任务 socket-->bind-->listen-->accept-->recv-->send-->close
322
323```c
324int wifi_server(void)
325{
326 int server_fd, ret;
327
328 while(1)
329 {
330 server_fd = socket(AF_INET, SOCK_STREAM, 0); //AF_INET:IPV4;SOCK_STREAM:TCP
331 // server_fd = lwip_socket(AF_INET, SOCK_STREAM, 0); //AF_INET:IPV4;SOCK_STREAM:TCP
332 if (server_fd < 0)
333 {
334 printf("create socket fail!\n");
335 return -1;
336 }
337
338 /*设置调用close(socket)后,仍可继续重用该socket。调用close(socket)一般不会立即关闭socket,而经历TIME_WAIT的过程。*/
339 int flag = 1;
340 ret = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int));
341 if (ret != 0) {
342 printf("[CommInitTcpServer]setsockopt fail, ret[%d]!\n", ret);
343 }
344
345 struct sockaddr_in serv_addr = {0};
346 serv_addr.sin_family = AF_INET;
347 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址,需要进行网络序转换,INADDR_ANY:本地地址
348 // serv_addr.sin_addr.s_addr = inet_addr(OC_SERVER_IP); //IP地址,需要进行网络序转换,INADDR_ANY:本地地址
349 serv_addr.sin_port = htons(SERVER_PORT); //端口号,需要网络序转换
350 /* 绑定服务器地址结构 */
351 ret = bind(server_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
352 // ret = lwip_bind(server_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
353 if (ret < 0)
354 {
355 printf("socket bind fail!\n");
356 lwip_close(server_fd);
357 return -1;
358 }
359 /* 监听socket 此处不阻塞 */
360 ret = listen(server_fd, 64);
361 // ret = lwip_listen(server_fd, 64);
362 if(ret != 0)
363 {
364 printf("socket listen fail!\n");
365 lwip_close(server_fd);
366 return -1;
367 }
368 printf("[tcp server] listen:%d<%s:%d>\n",server_fd, inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
369 tcp_server_msg_handle(server_fd); //处理接收到的数据
370 LOS_Msleep(1000);
371 }
372}
373```
374
375连接客户端,并发送消息和接收消息
376
377```c
378void tcp_server_msg_handle(int fd)
379{
380 char buf[BUFF_LEN]; //接收缓冲区
381 socklen_t client_addr_len;
382 int cnt = 0, count;
383 int client_fd;
384 struct sockaddr_in client_addr = {0};
385
386 printf("waitting for client connect...\n");
387 /* 监听socket 此处会阻塞 */
388 client_fd = accept(fd, (struct sockaddr*)&client_addr, &client_addr_len);
389 // client_fd = lwip_accept(fd, (struct sockaddr*)&client_addr, &client_addr_len);
390 printf("[tcp server] accept <%s:%d>\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
391 while (1)
392 {
393 memset(buf, 0, BUFF_LEN);
394 printf("-------------------------------------------------------\n");
395 printf("[tcp server] waitting client msg\n");
396 count = recv(client_fd, buf, BUFF_LEN, 0); //read是阻塞函数,没有数据就一直阻塞
397 // count = lwip_read(client_fd, buf, BUFF_LEN); //read是阻塞函数,没有数据就一直阻塞
398 if (count == -1)
399 {
400 printf("[tcp server] recieve data fail!\n");
401 LOS_Msleep(3000);
402 break;
403 }
404 printf("[tcp server] rev client msg:%s\n", buf);
405 memset(buf, 0, BUFF_LEN);
406 sprintf(buf, "I have recieved %d bytes data! recieved cnt:%d", count, ++cnt);
407 printf("[tcp server] send msg:%s\n", buf);
408 send(client_fd, buf, strlen(buf), 0); //发送信息给client
409 // lwip_write(client_fd, buf, strlen(buf)); //发送信息给client
410 }
411 lwip_close(client_fd);
412 lwip_close(fd);
413}
414```
415
416## 编译调试
417
418### 修改 BUILD.gn 文件
419
420修改 `vendor/lockzhiner/lingpi/sample` 路径下 BUILD.gn 文件,指定 `b7_wifi_tcp` 参与编译。
421
422```r
423"b7_wifi_tcp",
424```
425
426在主目录下输入编译命令。
427
428```shell
429hb build -f
430```
431
432### 运行结果
433
434示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,串口0显示如下:
435
436```c
437[wifi_api:D]netif setup ...
438[coonfig_network:D]rknetwork EnableWifi done
439
440[coonfig_network:D]rknetwork SetWifiScan after g_wificonfig.bssid:
441
442[wifi_api_internal:D]Connect to (SSID=凌智电子)
443[wifi_api_internal:D]derive psk ...
444[wifi_api_internal:D]derive psk done
445[wifi_api_internal:D]recovery process ...
446[wifi_api_internal:D]AP BSSID (30:5f:77:80:80:b0)
447[coonfig_network:I]ConnectTo (凌智电子) done
448[coonfig_network:D]rknetwork IP (192.168.2.50)
449[coonfig_network:D]network GW (192.168.2.1)
450[coonfig_network:D]network NETMASK (255.255.255.0)
451[WIFI_DEVICE:E]l o num:0 127.0.0.1
452[WIFI_DEVICE:E]w l num:1 192.168.2.50
453[coonfig_network:D]set network GW
454[coonfig_network:D]network GW (192.168.2.1)
455[coonfig_network:D]network NETMASK (255.255.255.0)
456[tcp:D]rknetwork IP (192.168.2.50)
457[tcp:D]network GW (192.168.2.1)
458[tcp:D]network NETMASK (255.255.255.0)
459[WIFI_DEVICE:E]l o num:0 127.0.0.1
460[WIFI_DEVICE:E]w l num:1 192.168.2.50
461[tcp:D]set network GW
462[tcp:D]network GW (192.168.2.1)
463[tcp:D]network NETMASK (255.255.255.0)
464[tcp client] connect:50<192.168.2.49:6666>
465[tcp server] listen:51<0.0.0.0:6666>
466waitting for client connect...
467------------------------------------------------------------
468[tcp client] send:TCP TEST cilent send:1
469[tcp client] client sendto msg to server 22,waitting server respond msg!!!
470[tcp client] rev:
471------------------------------------------------------------
472[tcp client] send:TCP TEST cilent send:2
473[tcp client] client sendto msg to server 22,waitting server respond msg!!!
474[tcp client] recieve data fail!
475[tcp client] connect:50<192.168.2.49:6666>
476connect server failed...1
477connect server failed...2
478[tcp server] accept <0.0.0.0:0>
479-------------------------------------------------------
480[tcp server] waitting client msg
481------------------------------------------------------------
482[tcp client] send:TCP TEST cilent send:1
483[tcp client] client sendto msg to server 22,waitting server respond msg!!!
484[tcp client] rev:凌智电子服务端
485------------------------------------------------------------
486[tcp client] send:TCP TEST cilent send:2
487[tcp client] client sendto msg to server 22,waitting server respond msg!!!
488[tcp server] rev client msg:凌智电子客户端
489[tcp server] send msg:I have recieved 14 bytes data! recieved cnt:1
490-------------------------------------------------------
491[tcp server] waitting client msg
492[tcp client] rev:凌智电子服务端
493------------------------------------------------------------
494[tcp client] send:TCP TEST cilent send:3
495[tcp client] client sendto msg to server 22,waitting server respond msg!!!
496[tcp server] rev client msg:凌智电子客户端
497[tcp server] send msg:I have recieved 14 bytes data! recieved cnt:2
498-------------------------------------------------------
499[tcp server] waitting client msg
500[tcp server] rev client msg:凌智电子客户端
501[tcp server] send msg:I have recieved 14 bytes data! recieved cnt:3
502-------------------------------------------------------
503[tcp server] waitting client msg
504```
505
506当log中出现以下信息表示小凌派的tcp客户端和服务端任务已启动
507
508```c
509[tcp client] connect:50<192.168.2.49:6666>
510[tcp server] listen:51<0.0.0.0:6666>
511```
512
513此时用网络调试助手查看并收发消息。
514
515
516