• Home
Name Date Size #Lines LOC

..--

BUILD.gnD12-May-2024889 2521

README_zh.mdD12-May-202416.1 KiB516396

wifi_tcp_example.cD12-May-20249.5 KiB286212

README_zh.md

1# 小凌派-RK2206开发板基础外设开发——wifi-tcp通信
2
3本示例将演示如何在小凌派-RK2206开发板上使用wifi进行tcp通信
4
5![小凌派-RK2206开发板](../../docs/figures/lockzhiner-rk2206.jpg)
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![wifi ip地址](/vendor/lockzhiner/lingpi/docs/figures/wifi_tcp/2022-05-09_14-17-53wifi_ip.png)
26
27### 确认pc与小凌派在同一局域网,查看PC的IP地址和网关
28
29在控制台输入 ``ipconfig``
30图如下所示:
31![pc ip地址](/vendor/lockzhiner/lingpi/docs/figures/wifi_tcp/2022-05-09_14-25-56pc_ip.png)
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![pc 网络调试工具](/vendor/lockzhiner/lingpi/docs/figures/wifi_tcp/2022-05-09_14-41-34网络调试工具.png)
43
44查看log 等待小凌派的tcp客户端和服务端任务启动
45![tcp start](/vendor/lockzhiner/lingpi/docs/figures/wifi_tcp/2022-05-09_14-45-59tcp_start.png)
46
47当小凌派tcp客户端和服务端启动后, 再用网络调试助手点击启动客户端和服务端
48![网络调试工具 start](/vendor/lockzhiner/lingpi/docs/figures/wifi_tcp/2022-05-09_14-55-05pc_tool_start.png)
49
50然后就可以通过网络工具与小凌派通信了
51![网络调试工具 tcp_msg](/vendor/lockzhiner/lingpi/docs/figures/wifi_tcp/2022-05-09_15-00-15tcp_msg.png)
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![网络调试工具 tcp_msg](/vendor/lockzhiner/lingpi/docs/figures/wifi_tcp/2022-05-09_15-00-15tcp_msg.png)
515
516