• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2  Copyright (C) 2024 HiHope Open Source Organization .
3  Licensed under the Apache License, Version 2.0 (the "License");
4  you may not use this file except in compliance with the License.
5  You may obtain a copy of the License at
6 
7      http://www.apache.org/licenses/LICENSE-2.0
8 
9  Unless required by applicable law or agreed to in writing, software
10  distributed under the License is distributed on an "AS IS" BASIS,
11  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  See the License for the specific language governing permissions and
13  limitations under the License.
14  */
15 
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <errno.h>
19 #include <string.h>
20 #include "lwip/sockets.h"   // lwIP TCP/IP协议栈
21 #include "oled_ssd1306.h"
22 
23 // 发送的数据
24 static char request[] = "send_data";
25 // 接收的数据
26 static char response[100] = "";
27 // OLED显示的数据
28 static char display_data[11] = "";
29 int c = 1;
30 
31 /* @brief UDP客户端测试函数
32    @param1 host UDP服务端IP地址
33    @param2 port UDP服务端端口
34 */
UdpClientTest(const char * host,unsigned short port)35 void UdpClientTest(const char *host, unsigned short port)
36 {
37     ssize_t ret = 0;
38 
39     // 创建一个UDP Socket
40     int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
41 
42     // 用于设置服务端的地址信息
43     struct sockaddr_in toAddr = {0};
44 
45     // 使用IPv4协议
46     toAddr.sin_family = AF_INET;
47 
48     // 端口号,从主机字节序转为网络字节序
49     toAddr.sin_port = htons(port);
50 
51     // 将服务端IP地址转化为标准格式
52     if (inet_pton(AF_INET, host, &toAddr.sin_addr) <= 0)
53     {
54         // 转化失败
55         printf("inet_pton failed!\r\n");
56         // 关闭socket
57         lwip_close(sockfd);
58     }
59 
60     // 发送数据API
61     // UDP socket每次发送都必须先指定目标主机和端口,主机可以是多播地址,发送数据的时候,使用本地随机端口
62     /*
63     -参数-
64     s:socket文件描述符
65     dataptr:要发送的数据
66     size:要发送的数据的长度,最大65332字节
67     flags:消息传输标志位
68     to:目标的地址信息
69     tolen:目标的地址信息长度
70     -返回值-
71      发送的字节数,如果出错,返回-1
72      */
73     ret = sendto(sockfd, request, sizeof(request), 0, (struct sockaddr *)&toAddr, sizeof(toAddr));
74     if (ret < 0)
75     {
76         // 发送失败
77         printf("sendto failed!\r\n");
78     }
79 
80     // 发送成功
81     printf("send UDP message {%s} %ld done!\r\n", request, ret);
82     // 发送方的地址信息
83     struct sockaddr_in fromAddr = {0};
84 
85     //地址信息长度
86     socklen_t fromLen = sizeof(fromAddr);
87 
88 
89     while (c)
90     {
91         memset(display_data,0,strlen(display_data));
92         memset(response,0,strlen(response));
93 
94         /*在本地随机端口上面接收数据,可以通过fromAddr参数可以得到发送方的信息(主机、端口号)*/
95         /*
96          -参数-
97          s:socket文件描述符
98          buffer:接收数据的缓冲区的地址
99          length:接收数据的缓冲区的长度
100          flags:消息接收标志位
101          address:发送方的地址信息
102          address_len:发送方的地址信息长度
103 
104          -返回值-
105          接收的字节数,如果出错,返回-1
106         */
107         ret = recvfrom(sockfd, &response, sizeof(response), 0, (struct sockaddr *)&fromAddr, &fromLen);
108 
109         // 检查接口返回值,小于0表示接收失败
110         if (ret <= 0)
111         {
112             // 接收失败,或者收到0长度的数据
113             printf("recvfrom failed or abort, %ld, %d!\r\n", ret, errno);
114         }
115 
116         response[ret] = '\0';
117 
118         // 显示发送方的地址信息
119         printf("peer info: ipaddr = %s, port = %d\r\n", inet_ntoa(fromAddr.sin_addr), ntohs(fromAddr.sin_port));
120         // 接收成功,输出日志,OLED显示收到的收据,最多显示10个字符
121         printf(" recv_data{%s} from server!\r\n", response);
122         OledShowString(0, 5,"recv:", FONT6x8);
123         OledShowString(40, 5,"          ", FONT6x8);
124         memcpy(display_data,response,10);
125         display_data[11] = '\0';
126         OledShowString(40, 5,display_data, FONT6x8);
127 
128         osDelay(100);
129 
130     }
131 
132     // 关闭socket
133    // lwip_close(sockfd);
134 }
135