• Home
Name Date Size #Lines LOC

..--

wifi/12-May-2024-257189

BUILD.gnD12-May-2024864 2623

README.mdD12-May-20244 KiB12992

udp_client_demo.cD12-May-20243.2 KiB10358

README.md

1# BearPi-HM_Nano开发板WiFi编程开发——UDP客户端
2本示例将演示如何在BearPi-HM_Nano开发板上使用socket编程创建UDP客户端,向服务端发送固定消息并接收服务端返回的消息。
3
4
5## socket API分析
6本案例主要使用了以下几个API完socket编程实验。
7### socket()
8
9```c
10sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) //AF_INT:ipv4, SOCK_DGRAM:udp协议
11```
12**描述:**
13
14在网络编程中所需要进行的第一件事情就是创建一个socket,无论是客户端还是服务器端,都需要创建一个socket,该函数返回socket文件描述符,类似于文件描述符。socket是一个结构体,被创建在内核中。
15### sendto()
16```c
17int sendto(socket s, const void *msg, int len, unsigned int flags, const struct sockaddr *to , int token);
18```
19**描述:**
20
21sendto() 用来将数据由指定的socket传给对方主机。参数s为已建立连接的socket。参数msg指向待发送的数据,参数flags 一般设0。
22
23### recvfrom()
24```c
25int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
26```
27**描述:**
28从指定地址接收UDP数据包。
29
30
31**参数:**
32
33|参数名|描述|
34|:--|:------|
35| s | socket描述符。  |
36| buf | 消息接收后的缓冲区。  |
37| len | 缓冲区的容量。  |
38| flags | 该参数一般为0。  |
39| from | 指向发送数据的对端地址信息的结构体,如果为NULL,不储存对端地址。  |
40| fromlen | 指向from结构体长度值,如果from为NULL,该值也应为NULL。  |
41
42
43
44## 软件设计
45
46**主要代码分析**
47
48完成UDP的通信过程需要以下几步。
49
501. 通过 `socket` 接口创建一个socket,`AF_INT`表示ipv4,`SOCK_DGRAM`表示使用dup协议。
512. 调用 `sendto` 接口发送数据到服务端。
523. 调用 `recvfrom` 接口接收服务端发来的数据。
53
54
55```c
56static void UDPClientTask(void)
57{
58    //在sock_fd 进行监听,在 new_fd 接收新的链接
59    int sock_fd;
60
61    //服务器的地址信息
62    struct sockaddr_in send_addr;
63    socklen_t addr_length = sizeof(send_addr);
64    char recvBuf[512];
65
66    //连接Wifi
67    WifiConnect(CONFIG_WIFI_SSID, CONFIG_WIFI_PWD);
68
69    //创建socket
70    if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
71        perror("create socket failed!\r\n");
72        exit(1);
73    }
74
75    //初始化预连接的服务端地址
76    send_addr.sin_family = AF_INET;
77    send_addr.sin_port = htons(CONFIG_SERVER_PORT);
78    send_addr.sin_addr.s_addr = inet_addr(CONFIG_SERVER_IP);
79    addr_length = sizeof(send_addr);
80
81    //总计发送 count 次数据
82    while (1) {
83        bzero(recvBuf, sizeof(recvBuf));
84
85        //发送数据到服务远端
86        sendto(sock_fd, send_data, strlen(send_data), 0, (struct sockaddr *)&send_addr, addr_length);
87
88        //线程休眠一段时间
89        sleep(TASK_DELAY_10S);
90
91        //接收服务端返回的字符串
92        recvfrom(sock_fd, recvBuf, sizeof(recvBuf), 0, (struct sockaddr *)&send_addr, &addr_length);
93        printf("%s:%d=>%s\n", inet_ntoa(send_addr.sin_addr), ntohs(send_addr.sin_port), recvBuf);
94    }
95
96    //关闭这个 socket
97    closesocket(sock_fd);
98}
99```
100
101## 编译调试
102
103### 修改 BUILD.gn 文件
104
105修改 `device\board\bearpi\bearpi_hm_nano\app` 路径下 BUILD.gn 文件,指定 `udp_client` 参与编译。
106```r
107#"D1_iot_wifi_sta:wifi_sta",
108#"D2_iot_wifi_sta_connect:wifi_sta_connect",
109"D3_iot_udp_client:udp_client",
110#"D4_iot_tcp_server:tcp_server",
111#"D5_iot_mqtt:iot_mqtt",
112#"D6_iot_cloud_oc:oc_mqtt",
113```
114
115
116### 运行结果<a name="section18115713118"></a>
117
118使用 Socket tool 创建UDP服务端用于测试,如下图所示。
119
120![创建UDP服务端](../../docs/figures/D3_iot_udp_client/createupdservice.png)
121
122示例代码编译烧录后,按下开发板的RESET按键,在socket tool的数据发送窗口输入要发送的数据,点击发送后开发板会回复固定消息,如下图所示,且开发板收到消息后会通过日志打印出来。
123
124```
125192.168.0.175:8888=>Hello! BearPi-HM_nano UDP Client!
126```
127
128![UDP发送数据](../../docs/figures/D3_iot_udp_client/UPDSendData.png)
129