写点什么

鸿蒙网络编程系列 2-UDP 回声服务器的实现

作者:长弓三石
  • 2024-10-22
    广东
  • 本文字数:2782 字

    阅读完需:约 9 分钟

1.回声服务器简介

回声服务器指的是这样一种服务器,它接受客户端的连接,并且把收到的数据原样返回给客户端,本文将使用 UDP 协议实现一个回声服务器,关于 UDP 通讯相关方法的介绍可以参考上一篇博文:鸿蒙网络编程系列1-UDP通讯示例,最终应用的界面如下图所示:


2.实现思路

首先创建一个 UDP 实例,然后绑定到指定的端口,再订阅 message 事件,在处理该事件的时候,输出接收到的消息并且把该消息通过 send 方法发回客户端。

3.实现步骤

步骤 1:创建 Empty Ability 项目。


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


"requestPermissions": [

{

​ "name": "ohos.permission.INTERNET"

},

{

​ "name": "ohos.permission.GET_WIFI_INFO"

}

]


这里分别添加了访问互联网和访问 WIFI 信息的权限。


步骤 3:在 Index.ets 文件里添加如下的代码:


import socket from '@ohos.net.socket';import wifiManager from '@ohos.wifiManager';import systemDateTime from '@ohos.systemDateTime';import util from '@ohos.util';import hilog from '@ohos.hilog';
//执行UDP通讯的对象let udpSocket = socket.constructUDPSocketInstance();
//说明:本地的IP地址不是必须知道的,绑定时绑定到IP:0.0.0.0即可,显示本地IP地址的目的是方便对方发送信息过来//本地IP的数值形式let ipNum = wifiManager.getIpInfo().ipAddress//本地IP的字符串形式let localIp = (ipNum >>> 24) + '.' + (ipNum >> 16 & 0xFF) + '.' + (ipNum >> 8 & 0xFF) + '.' + (ipNum & 0xFF);
@Entry@Componentstruct Index { //连接、通讯历史记录 @State msgHistory: string = '' //本地端口 @State localPort: number = 9999 scroller: Scroller = new Scroller()
build() { Row() { Column() { Text("UDP回声服务器") .fontSize(14) .fontWeight(FontWeight.Bold) .width('100%') .textAlign(TextAlign.Center) .padding(10)
Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { Text("本地IP和端口:") .width(100) .fontSize(14) .flexGrow(0) Text(localIp) .width(110) .fontSize(14) .flexGrow(0) TextInput({ text: this.localPort.toString() }) .type(InputType.Number) .onChange((value) => { this.localPort = parseInt(value) }) .width(80) .flexGrow(3)
Button("绑定") .onClick(() => { this.bind2Port() }) .width(80) .fontSize(14) .flexGrow(0)
}.width('100%') .padding(10)
Scroll(this.scroller) { Text(this.msgHistory) .textAlign(TextAlign.Start) .padding(10) .width('100%') .backgroundColor(0xeeeeee) } .align(Alignment.Top) .backgroundColor(0xeeeeee) .height(300) .flexGrow(1) .scrollable(ScrollDirection.Vertical) .scrollBar(BarState.On) .scrollBarWidth(20) } .width('100%') .justifyContent(FlexAlign.Start) .height('100%') } .height('100%') }
//发送消息到目的ip和端口 sendMsg2Target(address: string, port: number, msg: string) { //目的ip和端口 let remoteAddress = { address: address, port: port, family: 1 } udpSocket.send({ data: msg, address: remoteAddress }) .then(async () => { hilog.info(0x0000, 'sendMsg2Target', '%{public}s:%{public}d %{public}s', remoteAddress.address, remoteAddress.port, msg) }) .catch((e) => { hilog.error(0x0000, 'sendMsg2Target', '%{public}s:%{public}d %{public}s', remoteAddress.address, remoteAddress.port, e.message) }) }
//绑定本地端口 async bind2Port() { //本地地址 let localAddress = { address: "0.0.0.0", port: this.localPort, family: 1 }
await udpSocket.bind(localAddress) .then(() => { this.msgHistory = 'bind success' + "\r\n"; }) .catch((e) => { this.msgHistory = 'bind fail' + e.message + "\r\n"; })
//收到消息时的处理 udpSocket.on("message", async (value) => { let msg = buf2String(value.message) let remoteIP = value.remoteInfo.address let remotePort = value.remoteInfo.port //对端ip地址和端口的字符串形式 let remoteAddr = "[" + remoteIP + ":" + remotePort.toString() + "]:" let time = await getCurrentTimeString() this.msgHistory += remoteAddr + msg + time + "\r\n" this.scroller.scrollEdge(Edge.Bottom)
//把收到的消息发回发送方 this.sendMsg2Target(remoteIP, remotePort, msg) }) }}
//同步获取当前时间的字符串形式async function getCurrentTimeString() { let time = "" await systemDateTime.getDate().then( (date) => { time = date.getHours().toString() + ":" + date.getMinutes().toString() + ":" + date.getSeconds().toString() } ) return "[" + time + "]"}
//ArrayBuffer转utf8字符串function buf2String(buf: ArrayBuffer) { let msgArray = new Uint8Array(buf); let textDecoder = util.TextDecoder.create("utf-8"); return textDecoder.decodeWithStream(msgArray)}
复制代码


步骤 4:编译运行,可以部署到模拟器或者真机上。


步骤 5:配置本地端口,然后单击绑定按钮绑定到本地指定的端口即可。


步骤 6:启动 UDP 客户端测试,这里使用 PC 端的一个 UDP 客户端程序,如下图所示:



先后发送了两段文字,以 S 开头的是服务端回送的内容,回声服务器的截图内容如下所示:


4.注意事项

目前的鸿蒙系统其实不适合作为服务端使用,因为应用切换到后台后就会被挂起,这时候就起不到服务器的功能了,所以本示例需要保持在前端,否则会接收不到消息。


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


本文源码地址:


https://gitee.com/zl3624/harmonyos_network_samples/tree/master/code/udp/UdpEchoServer


本系列源码地址:


https://gitee.com/zl3624/harmonyos_network_samples


发布于: 刚刚阅读数: 6
用户头像

长弓三石

关注

还未添加个人签名 2024-10-16 加入

二十多年软件开发经验的软件架构师,华为HDE、华为云HCDE、仓颉语言CLD、CCS,著有《仓颉语言网络编程》、《仓颉语言元编程》、《仓颉语言实战》、《鲲鹏架构入门与实战》等书籍,清华大学出版社出版。

评论

发布
暂无评论
鸿蒙网络编程系列2-UDP回声服务器的实现_DevEco Studio_长弓三石_InfoQ写作社区