鸿蒙网络编程系列47-仓颉版UDP客户端

1. UDP通讯简介

本系列的第1篇文章《鸿蒙网络编程系列1-UDP通讯示例》中基于ArkTS语言在API 9的环境下演示了UDP通讯的基础用法,本文将使用仓颉语言在API 12的环境中实现类似的功能。这可能听起来有点不太现实,在ArkTS语言下可以利用kit.NetworkKit下的socket模块,该模块包含UDPSocket类,使用该类可以进行UDP通讯。但是,截止到目前为止,仓颉适配鸿蒙的API中还没有提供对于该能力的封装,要实现仓颉版的UDP通讯不就是缘木求鱼嘛,毕竟巧妇难为无米之炊,只能等到提供类似API后才可以实现。

但是,别忘了,仓颉本身也是一门强大的语言,即使不使用鸿蒙的API,也可以实现UDP通讯–甚至功能更加强大!仓颉内置了std.socket模块,该模块包含UdpSocket类库,该类是UDP协议的封装,本文将基于该类进行UDP通讯,演示UDP客户端的实现。

2. UDP通讯演示

本示例运行后的页面如图所示:

输入绑定的本地端口,默认是9999,再输入对端UDP应用的IP地址和端口,如果没有合适的,也可以使用应用自身做为对端的UDP应用,这种情况下,对端iP地质使用127.0.0.0即可,然后单击“绑定”按钮进行绑定,如图所示,绑定到了9999端口:

绑定成功后,在信息输入框输入要发送的信息,比如“Hi,Server!”,再单击“发送”按钮,即可发送UDP消息给对端,如图所示:

可以看到,UDP消息成功发送并接收。

3. UDP通讯示例编写

下面详细介绍创建该示例的步骤(确保DevEco Studio已安装仓颉插件)。

步骤1:创建[Cangjie]Empty Ability项目。

步骤2:在module.json5配置文件加上对权限的声明:

"requestPermissions": [{"name": "ohos.permission.INTERNET"}]

这里添加了访问互联网的权限。

步骤3:在build-profile.json5配置文件加上仓颉编译架构:

"cangjieOptions": {"path": "./src/main/cangjie/cjpm.toml","abiFilters": ["arm64-v8a", "x86_64"]}

步骤4:在index.cj文件里添加如下的代码:

package ohos_app_cangjie_entryimport ohos.base.*
import ohos.component.*
import ohos.state_manage.*
import ohos.state_macro_manage.*
import std.collection.HashMap
import ohos.net.http.*
import ohos.file_picker.*
import ohos.ability.getStageContext
import ohos.ability.*
import ohos.file_fs.*
import std.time.DateTime
import std.convert.*
import std.net.*
import std.socket.*@Entry
@Component
class EntryView {@Statevar title: String = '仓颉版UDP客户端示例';//连接、通讯历史记录@Statevar msgHistory: String = ''//客户端端口@Statevar clientPort: UInt16 = 9999//客户端绑定地址@Statevar clientAddress = "0.0.0.0"//回显服务器端口@Statevar serverPort: UInt16 = 9999//回显服务器地址@Statevar serverAddress = "127.0.0.1"//要发送的信息@Statevar sendMsg = ""//绑定状态@Statevar bindState = false//UDP客户端var udpClient: ?UdpSocket = Nonelet scroller: Scroller = Scroller()func build() {Row {Column {Text(title).fontSize(14).fontWeight(FontWeight.Bold).width(100.percent).textAlign(TextAlign.Center).padding(10)Flex(FlexParams(justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center)) {Text("绑定的本地端口:").fontSize(14)TextInput(text: clientPort.toString()).onChange({value => clientPort = UInt16.parse(value)}).setType(InputType.Number).width(100).fontSize(11).flexGrow(1)Button("绑定").onClick {evt => bind()}.enabled(!bindState).width(70).fontSize(14)}.width(100.percent).padding(10)Flex(FlexParams(justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center)) {Text("对端IP地址和端口:").fontSize(14)TextInput(text: serverAddress).onChange({value => serverAddress = value}).width(100).fontSize(11).flexGrow(1)Text(":").fontSize(14)TextInput(text: serverPort.toString()).onChange({value => serverPort = UInt16.parse(value)}).setType(InputType.Number).width(80).fontSize(11)}.width(100.percent).padding(10)Flex(FlexParams(justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center)) {TextInput(placeholder: "输入要发送的信息", text: sendMsg).onChange({value => sendMsg = value}).width(100).fontSize(11).flexGrow(1)Button("发送").onClick {evt => sendMessage()}.enabled(bindState && sendMsg != "").width(70).fontSize(14)}.width(100.percent).padding(10)Scroll(scroller) {Text(msgHistory).textAlign(TextAlign.Start).padding(10).width(100.percent).backgroundColor(0xeeeeee)}.align(Alignment.Top).backgroundColor(0xeeeeee).height(300).flexGrow(1).scrollable(ScrollDirection.Vertical).scrollBar(BarState.On).scrollBarWidth(20)}.width(100.percent).height(100.percent)}.height(100.percent)}func bind() {udpClient = UdpSocket(bindAt: clientPort)udpClient?.bind()msgHistory += "绑定到端口${clientPort}\r\n"let serverAddress = SocketAddress(serverAddress, serverPort)//连接UDP服务器udpClient?.connect(serverAddress)bindState = true//启动一个线程读取服务器的消息spawn {try {readFromEchoServer(udpClient.getOrThrow())} catch (exp: Exception) {msgHistory += "Error reading data from socket:${exp}\r\n"}}}//发送消息func sendMessage() {msgHistory += "C:${sendMsg}\r\n"udpClient?.send(sendMsg.toArray())}//从socket读取数据并输出func readFromEchoServer(echoSocket: UdpSocket) {//存放从socket读取数据的缓冲区let buffer = Array<UInt8>(1024, item: 0)while (true) {//从socket读取数据var readCount = echoSocket.receive(buffer)//把接收到的数据转换为字符串let content = String.fromUtf8(buffer[0..readCount])//输出读取的内容,加上前缀S:msgHistory += "S:${content}\r\n"}}
}

步骤5:编译运行,可以使用模拟器或者真机。

步骤6:按照本文第2部分“UDP通讯演示”操作即可。

4. 代码分析

本文的示例代码及实现方式和ArkTS版本有极大的差异,特别是接收对端发送的UDP消息时,本示例是通过一个线程实现的,代码如下:

 //启动一个线程读取服务器的消息spawn {try {readFromEchoServer(udpClient.getOrThrow())} catch (exp: Exception) {msgHistory += "Error reading data from socket:${exp}\r\n"}}

该线程会启动readFromEchoServer函数,该函数循环从UDP端口读取数据,并且把读取到的数据转换为字符串通过日志输出,代码如下:

        let buffer = Array<UInt8>(1024, item: 0)while (true) {//从socket读取数据var readCount = echoSocket.receive(buffer)//把接收到的数据转换为字符串let content = String.fromUtf8(buffer[0..readCount])//输出读取的内容,加上前缀S:msgHistory += "S:${content}\r\n"}

(本文作者原创,除非明确授权禁止转载)

本文源码地址:
https://gitee.com/zl3624/harmonyos_network_samples/tree/master/code/udp/UdpDemo4Cj

本系列源码地址:
https://gitee.com/zl3624/harmonyos_network_samples

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/14709.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Redis与IO多路复用

1. Redis与IO多路复用概述 1.1 Redis的单线程特性 Redis是一个高性能的键值存储系统&#xff0c;其核心优势之一便是单线程架构。在Redis 6.0之前&#xff0c;其所有网络IO和键值对的读写操作都是由一个主线程顺序串行处理的。这种设计简化了多线程编程中的锁和同步问题&…

HarmonyOS Next 组件或页面之间的所有通信(传参)方法总结

系列文章目录 【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器&#xff08;上&#xff09; 【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器&#xff08;下&#xff09; 【鸿蒙】HarmonyOS NEXT应用开发快速入门教程之布局篇&#xff08;上&#xff09; 【…

API接口:助力汽车管理与安全应用

随着汽车行业的飞速发展&#xff0c;越来越多的汽车管理技术被应用到交通安全和智慧交通系统中。在这一过程中&#xff0c;API接口起到了至关重要的作用。通过API接口&#xff0c;我们可以实现诸如车主身份验核、车辆信息查询等功能&#xff0c;从而为汽车智慧交通发展与安全应…

C哈的刷题计划之输出数字螺旋矩阵(1)

1、盲听C哈说 都说数据结构与算法是编程的核心&#xff0c;它们两个是内功与心法&#x1f600;&#xff0c;其它编程工具只是招式&#xff0c;学会了内功与心法&#xff0c;学习新事物&#xff08;这里特指层出不穷的IT技术&#xff09;就没有那么难了&#xff0c;实际上&#…

AD22Duplicate Net Names Wire问题

在验证的时候发现报了这个错误 我这个原理图都是用自定义的元件 只写在name引脚名字是会报这个错的 但是换成designator引脚标识就不会了 建议是name引脚名字和designator引脚标识都写 写成一样都行&#xff0c;就不会报这个错了&#xff0c;别空着

centos7上安装mysql

1.现查看虚拟机上有没有wget包&#xff0c;如果没有的话进行安装 yum install -y wget 2.进入MySQL :: Download MySQL Yum Repository下载mysql安装源 找到与linux相应的版本&#xff0c;复制地址&#xff0c;如果找不到地址&#xff0c;可以复制如下 3.下载mysql官方yum源 …

hadoop报错找不到主类

错误&#xff1a; (base) mpsmps3:~$ hadoop hadoop_map_redce-1.0-SNAPSHOT.jar MovieDriver /input/movies-to-be-predicted.txt Error: Could not find or load main class hadoop_map_redce-1.0-SNAPSHOT.jar解决办法&#xff1a; 1.输入命令 hadoop classpath配置好了ha…

使用 start-local 脚本在本地运行 Elasticsearch

警告&#xff1a;请勿将这些说明用于生产部署 本页上的说明仅适用于本地开发。请勿将此配置用于生产部署&#xff0c;因为它不安全。请参阅部署选项以获取生产部署选项列表。 使用 start-local 脚本在 Docker 中快速设置 Elasticsearch 和 Kibana 以进行本地开发或测试。 此设…

Day14 - CV项目实战:SAR飞机检测识别

论文原文&#xff1a; ​​​​​​SAR-AIRcraft-1.0:高分辨率SAR飞机检测识别数据集 - 中国知网 第一排的7张图片&#xff0c;普通人肉眼很难看出对应的是第二排的飞机。 还有上图里标注的飞机&#xff0c;外行根本看不明白&#xff0c;为什么这些是&#xff0c;其他的不是。…

Threejs 材质贴图、光照和投影详解

1. 材质和贴图 材质&#xff08;Material&#xff09;定义了物体表面的外观&#xff0c;包括颜色、光泽度、透明度等。贴图&#xff08;Textures&#xff09;是应用于材质的图像&#xff0c;它们可以增加物体表面的细节和真实感。 1.1材质类型 MeshBasicMaterial&#xff1a…

笔记整理—linux驱动开发部分(11)中断上下文

触摸屏分为两种&#xff0c;一种为电阻式触摸屏&#xff0c;另一种为电容式触摸屏。电阻式触摸屏&#xff08;x、x-、y、y-、AD&#xff09;有两种接口&#xff0c;一种为SOC自带的接口&#xff08;miscinput或platform&#xff09;&#xff0c;第二种为外部IC&#xff0c;通过…

网络编程示例之开发板测试

编译elf1_cmd_net程序 &#xff08;一&#xff09;设置交叉编译环境。 &#xff08;二&#xff09;查看elf1_cmd_net文件夹Makefile文件。查看当前编译规则&#xff0c;net_demo是编译整个工程&#xff0c;clean是清除工程。 &#xff08;三&#xff09;输入命令。 &#xff0…

【GD32】(一) 开发方式简介及标准库开发入门

文章目录 0 前言1 开发方式选择2 标准库模板的创建3 遇到的问题和解决方法 0 前言 因为项目关系&#xff0c;需要使用GD32。之前对此早有耳闻&#xff0c;知道这个是一个STM32的替代品&#xff0c;据说甚至可以直接烧录STM32的程序&#xff08;一般是同型号&#xff09;&#x…

Java NIO 核心知识总结

NIO 简介 在传统的 Java I/O 模型&#xff08;BIO&#xff09;中&#xff0c;I/O 操作是以阻塞的方式进行的。也就是说&#xff0c;当一个线程执行一个 I/O 操作时&#xff0c;它会被阻塞直到操作完成。这种阻塞模型在处理多个并发连接时可能会导致性能瓶颈&#xff0c;因为需…

Spring如何解决循环依赖的问题

Spring 如何解决循环依赖的问题 Spring 是通过三级缓存来解决循环依赖问题&#xff0c;第一级缓存里面存储完整的Bean实例&#xff0c;这些实例是可以直接被使用的&#xff0c;第二级缓存存储的是实例化后但是还没有设置属性值的Bean实例&#xff0c;也就是Bean里面的 依赖注入…

深度图变换器的新突破:DeepGraph

人工智能咨询培训老师叶梓 转载标明出处 在图变换器领域&#xff0c;尽管其全局注意力机制在图结构数据处理上显示出了巨大潜力&#xff0c;但现有的图变换器模型却普遍较浅&#xff0c;通常不超过12层。这一现象引发了学者们对于“增加层数是否能进一步提升图变换器性能”的深…

单体架构 IM 系统之 Server 节点状态化分析

基于 http 短轮询模式的单体架构的 IM 系统见下图&#xff0c;即客户端通过 http 周期性地轮询访问 server 实现消息的即时通讯&#xff0c;也就是我们前面提到的 “信箱模型”。“信箱模型” 虽然实现非常容易&#xff0c;但是消息的实时性不高。 我们在上一篇文章&#xff08…

阿里云通义大模型团队开源Qwen2.5-Coder:AI编程新纪元

&#x1f680; 11月12日&#xff0c;阿里云通义大模型团队宣布开源通义千问代码模型全系列&#xff0c;共6款Qwen2.5-Coder模型。这些模型在同等尺寸下均取得了业界最佳效果&#xff0c;其中32B尺寸的旗舰代码模型在十余项基准评测中均取得开源最佳成绩&#xff0c;成为全球最强…

计算机网络(8)数据链路层之子层

上一篇已经讲到数据链路层可以分为两个子层&#xff0c;这次将重点讲解子层的作用和ppp协议 数据链路层的子层 数据链路层通常被分为两个子层&#xff1a; 逻辑链路控制子层&#xff08;LLC&#xff0c;Logical Link Control&#xff09;&#xff1a; LLC子层负责在数据链路…

【操作系统】输入/输出(I/O)管理

王道笔记 一、I/O管理描述 1.1 I/O设备的概念和分类 1.1.1 什么是I/O设备 “I/O”就是“输入/输出”&#xff08;Input/Output&#xff09; I/O设备机会可以将数据输入到计算机&#xff0c;或者可以接收计算机输出数据的外部设备&#xff0c;属于计算机中的硬件部件。下图就…