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