HI3861学习笔记(22)——UDP客户端

2024-02-27 18:50

本文主要是介绍HI3861学习笔记(22)——UDP客户端,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、TCP与UDP优缺点

1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接。

2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。
TCP通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。

3、UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。

4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信。

5、TCP对系统资源要求较多,UDP对系统资源要求较少。

二、API说明

以下 UDP 接口位于 vendor\hisi\hi3861\hi3861\third_party\lwip_sack\include\sockets.h

业务BUILD.gn中包含路径

include_dirs = ["//utils/native/lite/include","//kernel/liteos_m/components/cmsis/2.0","//base/iot_hardware/interfaces/kits/wifiiot_lite","//foundation/communication/interfaces/kits/wifi_lite/wifiservice","//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",]
  • socket()
  • bind()
  • accept()
  • shutdown()
  • getpeername()
  • getsockopt()setsockopt()
  • close()
  • read()readv()write()writev()
  • recv()
  • send()sendmsg()sendto()
  • select()
  • fcntl()

三、UDP客户端

3.1 主要流程

3.1.1 第一步:新建socket

在网络编程中所需要进行的第一件事情就是创建一个socket,无论是客户端还是服务器端,都需要创建一个socket,该函数返回socket文件描述符,类似于文件描述符。socket是一个结构体,被创建在内核中。

//在sock_fd 进行监听,在 new_fd 接收新的链接
int sock_fd;//创建socket
if((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{perror("create socket failed!\r\n");exit(1);
}

3.1.2 第二步:配置将要连接的服务器信息(端口和IP)

按道理服务器的地址选择 255.255.255.255,意思是不指定局域网内的某一设备,局域网所有的设备如果监听了这个端口号,那么都可以收到hi3861发来的消息。但是实际好像就只能填UDP服务器的地址,而已只能发送,不能接收。

#define UDP_PROT  8888int addr_length;//服务器的地址信息
struct sockaddr_in send_addr;
socklen_t addr_length = sizeof(send_addr);//初始化预连接的服务端地址
send_addr.sin_family = AF_INET;
send_addr.sin_port = htons(UDP_PROT);
send_addr.sin_addr.s_addr = inet_addr("192.168.31.225");
addr_length = sizeof(send_addr);

3.1.3 第三步:发送数据

sendto() 用来将数据由指定的socket传给对方主机。参数s为已建好连线的socket。参数msg指向欲连线的数据内容,参数flags一般设0。

static const char *send_data = "Hello! I'm BearPi-HM_Nano UDP Client!\r\n";//发送数据到服务远端
sendto(sock_fd, send_data, strlen(send_data), 0, (struct sockaddr *)&send_addr, addr_length);

3.1.4 第四步:接收数据

char recvBuf[512];while (1)
{bzero(recvBuf, sizeof(recvBuf));...//线程休眠一段时间sleep(10);//接收服务端返回的字符串recvfrom(sock_fd, recvBuf, sizeof(recvBuf), 0, (struct sockaddr *)&send_addr, &addr_length);printf("%s:%d=>%s\n", inet_ntoa(send_addr.sin_addr), ntohs(send_addr.sin_port), recvBuf);
}

3.2 配置SSID和密码连接WIFI创建TCP客户端

wifi_connect.c

#include <stdio.h>
#include <string.h>
#include <unistd.h>#include "lwip/netif.h"
#include "lwip/netifapi.h"
#include "lwip/ip4_addr.h"
#include "lwip/api_shell.h"#include "cmsis_os2.h"
#include "hos_types.h"
#include "wifi_device.h"
#include "wifiiot_errno.h"
#include "ohos_init.h"#define DEF_TIMEOUT 15
#define ONE_SECOND 1#define SELECT_WIFI_SECURITYTYPE WIFI_SEC_TYPE_PSK  static void WiFiInit(void);
static void WaitSacnResult(void);
static int WaitConnectResult(void);
static void OnWifiScanStateChangedHandler(int state, int size);
static void OnWifiConnectionChangedHandler(int state, WifiLinkedInfo *info);
static void OnHotspotStaJoinHandler(StationInfo *info);
static void OnHotspotStateChangedHandler(int state);
static void OnHotspotStaLeaveHandler(StationInfo *info);static int g_staScanSuccess = 0;
static int g_ConnectSuccess = 0;
static int ssid_count = 0;
WifiEvent g_wifiEventHandler = {0};
WifiErrorCode error;#define SELECT_WLAN_PORT "wlan0"int WifiConnect(const char *ssid, const char *psk)
{WifiScanInfo *info = NULL;unsigned int size = WIFI_SCAN_HOTSPOT_LIMIT;static struct netif *g_lwip_netif = NULL;osDelay(200);printf("<--System Init-->\r\n");//初始化WIFIWiFiInit();//使能WIFIif (EnableWifi() != WIFI_SUCCESS){printf("EnableWifi failed, error = %d\r\n", error);return -1;}//判断WIFI是否激活if (IsWifiActive() == 0){printf("Wifi station is not actived.\r\n");return -1;}//分配空间,保存WiFi信息info = malloc(sizeof(WifiScanInfo) * WIFI_SCAN_HOTSPOT_LIMIT);if (info == NULL){return -1;}//轮询查找WiFi列表do{//重置标志位ssid_count = 0;g_staScanSuccess = 0;//开始扫描Scan();//等待扫描结果WaitSacnResult();//获取扫描列表error = GetScanInfoList(info, &size);}while(g_staScanSuccess != 1);//打印WiFi列表printf("********************\r\n");for(uint8_t i = 0; i < ssid_count; i++){printf("no:%03d, ssid:%-30s, rssi:%5d\r\n", i+1, info[i].ssid, info[i].rssi/100);}printf("********************\r\n");//连接指定的WiFi热点for(uint8_t i = 0; i < ssid_count; i++){if (strcmp(ssid, info[i].ssid) == 0){int result;printf("Select:%3d wireless, Waiting...\r\n", i+1);//拷贝要连接的热点信息WifiDeviceConfig select_ap_config = {0};strcpy(select_ap_config.ssid, info[i].ssid);strcpy(select_ap_config.preSharedKey, psk);select_ap_config.securityType = SELECT_WIFI_SECURITYTYPE;if (AddDeviceConfig(&select_ap_config, &result) == WIFI_SUCCESS){if (ConnectTo(result) == WIFI_SUCCESS && WaitConnectResult() == 1){printf("WiFi connect succeed!\r\n");g_lwip_netif = netifapi_netif_find(SELECT_WLAN_PORT);break;}}}if(i == ssid_count-1){printf("ERROR: No wifi as expected\r\n");while(1) osDelay(100);}}//启动DHCPif (g_lwip_netif){dhcp_start(g_lwip_netif);printf("begain to dhcp\r\n");}//等待DHCPfor(;;){if(dhcp_is_bound(g_lwip_netif) == ERR_OK){printf("<-- DHCP state:OK -->\r\n");//打印获取到的IP信息netifapi_netif_common(g_lwip_netif, dhcp_clients_info_show, NULL);break;}printf("<-- DHCP state:Inprogress -->\r\n");osDelay(100);}osDelay(100);return 0;
}static void WiFiInit(void)
{printf("<--Wifi Init-->\r\n");g_wifiEventHandler.OnWifiScanStateChanged = OnWifiScanStateChangedHandler;g_wifiEventHandler.OnWifiConnectionChanged = OnWifiConnectionChangedHandler;g_wifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoinHandler;g_wifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeaveHandler;g_wifiEventHandler.OnHotspotStateChanged = OnHotspotStateChangedHandler;error = RegisterWifiEvent(&g_wifiEventHandler);if (error != WIFI_SUCCESS){printf("register wifi event fail!\r\n");}else{printf("register wifi event succeed!\r\n");}
}static void OnWifiScanStateChangedHandler(int state, int size)
{if (size > 0){ssid_count = size;g_staScanSuccess = 1;}printf("callback function for wifi scan:%d, %d\r\n", state, size);return;
}static void OnWifiConnectionChangedHandler(int state, WifiLinkedInfo *info)
{if (info == NULL){printf("WifiConnectionChanged:info is null, stat is %d.\n", state);}else{if (state == WIFI_STATE_AVALIABLE){g_ConnectSuccess = 1;}else{g_ConnectSuccess = 0;}}
}static void OnHotspotStaJoinHandler(StationInfo *info)
{(void)info;printf("STA join AP\n");return;
}static void OnHotspotStaLeaveHandler(StationInfo *info)
{(void)info;printf("HotspotStaLeave:info is null.\n");return;
}static void OnHotspotStateChangedHandler(int state)
{printf("HotspotStateChanged:state is %d.\n", state);return;
}static void WaitSacnResult(void)
{int scanTimeout = DEF_TIMEOUT;while (scanTimeout > 0){sleep(ONE_SECOND);scanTimeout--;if (g_staScanSuccess == 1){printf("WaitSacnResult:wait success[%d]s\n", (DEF_TIMEOUT - scanTimeout));break;}}if (scanTimeout <= 0){printf("WaitSacnResult:timeout!\n");}
}static int WaitConnectResult(void)
{int ConnectTimeout = DEF_TIMEOUT;while (ConnectTimeout > 0){sleep(ONE_SECOND);ConnectTimeout--;if (g_ConnectSuccess == 1){printf("WaitConnectResult:wait success[%d]s\n", (DEF_TIMEOUT - ConnectTimeout));break;}}if (ConnectTimeout <= 0){printf("WaitConnectResult:timeout!\n");return 0;}return 1;
}

wifi_connect.h

#ifndef __WIFI_CONNECT_H__
#define __WIFI_CONNECT_H__int WifiConnect(const char *ssid,const char *psk);#endif /* __WIFI_CONNECT_H__ */

四、完整代码

编译时在业务BUILD.gn中包含路径

static_library("myapp") {sources = ["wifi_connect.c","hello_world.c"]cflags = [ "-Wno-unused-variable" ]cflags += [ "-Wno-unused-but-set-variable" ]cflags += [ "-Wno-unused-parameter" ]include_dirs = ["//utils/native/lite/include","//kernel/liteos_m/components/cmsis/2.0","//base/iot_hardware/interfaces/kits/wifiiot_lite","//foundation/communication/interfaces/kits/wifi_lite/wifiservice","//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",]
}

hello_world.c

#include <stdio.h>
#include <unistd.h>#include "ohos_init.h"
#include "cmsis_os2.h"#include "wifi_device.h"
#include "lwip/netifapi.h"
#include "lwip/api_shell.h"
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include "lwip/sockets.h"
#include "wifi_connect.h"#define UDP_PROT 3333//在sock_fd 进行监听,在 new_fd 接收新的链接
int sock_fd;int addr_length;
static const char *send_data = "Hello! I'm BearPi-HM_Nano UDP Client!\r\n";//服务器的地址信息
struct sockaddr_in send_addr;static void UDPClientTask(void)
{socklen_t addr_length = sizeof(send_addr);char recvBuf[512];//连接WifiWifiConnect("406", "82069909");//创建socketif ((sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) == -1){perror("create socket failed!\r\n");exit(1);}//初始化预连接的服务端地址send_addr.sin_family = AF_INET;send_addr.sin_port = htons(UDP_PROT);send_addr.sin_addr.s_addr = inet_addr("192.168.31.225");addr_length = sizeof(send_addr);while (1){bzero(recvBuf, sizeof(recvBuf));//发送数据到服务远端sendto(sock_fd, send_data, strlen(send_data), 0, (struct sockaddr *)&send_addr, addr_length);//线程休眠一段时间sleep(10);//接收服务端返回的字符串recvfrom(sock_fd, recvBuf, sizeof(recvBuf), 0, (struct sockaddr *)&send_addr, &addr_length);printf("%s:%d=>%s\n", inet_ntoa(send_addr.sin_addr), ntohs(send_addr.sin_port), recvBuf);}//关闭这个 socketclosesocket(sock_fd);
}static void UDPClientDemo(void)
{osThreadAttr_t attr;attr.name = "UDPClientTask";attr.attr_bits = 0U;attr.cb_mem = NULL;attr.cb_size = 0U;attr.stack_mem = NULL;attr.stack_size = 10240;attr.priority = osPriorityNormal;if (osThreadNew((osThreadFunc_t)UDPClientTask, NULL, &attr) == NULL){printf("[UDPClientDemo] Falied to create UDPClientTask!\n");}
}APP_FEATURE_INIT(UDPClientDemo);

查看打印:


• 由 Leung 写于 2022 年 3 月 15 日

• 参考:【鸿蒙2.0设备开发教程】小熊派HarmonyOS 鸿蒙·季 开发教程

这篇关于HI3861学习笔记(22)——UDP客户端的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/753293

相关文章

SpringBoot实现websocket服务端及客户端的详细过程

《SpringBoot实现websocket服务端及客户端的详细过程》文章介绍了WebSocket通信过程、服务端和客户端的实现,以及可能遇到的问题及解决方案,感兴趣的朋友一起看看吧... 目录一、WebSocket通信过程二、服务端实现1.pom文件添加依赖2.启用Springboot对WebSocket

QT实现TCP客户端自动连接

《QT实现TCP客户端自动连接》这篇文章主要为大家详细介绍了QT中一个TCP客户端自动连接的测试模型,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录版本 1:没有取消按钮 测试效果测试代码版本 2:有取消按钮测试效果测试代码版本 1:没有取消按钮 测试效果缺陷:无法手动停

Nacos客户端本地缓存和故障转移方式

《Nacos客户端本地缓存和故障转移方式》Nacos客户端在从Server获得服务时,若出现故障,会通过ServiceInfoHolder和FailoverReactor进行故障转移,ServiceI... 目录1. ServiceInfoHolder本地缓存目录2. FailoverReactorinit

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学