社区编辑申请
注册/登录
OpenHarmony与HarmonyOS实现信息交流(一)
系统 OpenHarmony
本次,我将分享如何在搭载HarmonyOS的手机和搭载OpenHarmony的开发板上,实现socket对话!

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

在过去很长一段时间,我都非常希望能够将OpenHarmony与HarmonyOS设备进行一个联动,但是碍于一些底层接口未完善一直无法实现。但是在前几个月,OpenHarmony3.1 带来了更多可能。本次,我将分享如何在搭载HarmonyOS的手机和搭载OpenHarmony的开发板上,实现socket对话!

一、效果演示

#夏日挑战赛# 【FFH】OpenHarmony与HarmonyOS实现信息交流(一)-开源基础软件社区

二、HarmonyOS侧

1、新建一个JAVA工程,编写简单的测试页面

#夏日挑战赛# 【FFH】OpenHarmony与HarmonyOS实现信息交流(一)-开源基础软件社区

  • ability_main.xml (主页面)。
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="center"
ohos:orientation="vertical">
<TextField
ohos:id="$+id:sendfield"
ohos:height="200px"
ohos:width="800px"
ohos:bottom_margin="32vp"
ohos:text_size="32fp"
ohos:hint="请输入发送信息"
ohos:background_element="$graphic:tfbg"
/>
<Button
ohos:id="$+id:btn"
ohos:height="120px"
ohos:width="300px"
ohos:text="启动"
ohos:text_size="32fp"
ohos:background_element="$graphic:btn"
/>
<Text
ohos:id="$+id:text"
ohos:top_margin="50vp"
ohos:height="match_content"
ohos:width="match_content"
ohos:text_size="32fp"
ohos:text="暂无消息"


/>
<Text
ohos:id="$+id:localip"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="本机IP"
ohos:top_margin="30vp"
ohos:text_size="32fp"
/>
<TextField
ohos:id="$+id:textfield"
ohos:height="200px"
ohos:width="800px"
ohos:top_margin="50vp"
ohos:text_size="32fp"
ohos:hint="请输入IP地址"
ohos:background_element="$graphic:tfbg"
/>

</DirectionalLayout>

这是我自己编写的一个测试页面,但不是最重要的。

2、编写socket功能

目前,鸿蒙的Socket通信功能只能在JAVA侧实现,并且官网对相关的功能解析不够全面,但是足够实现UDP通信。

这里直接参考官网,可以快速实现Socket功能,传送门:​​JAVA-socket

在MainAbilitySlice中编写两个主要函数,并结合个人情况绑定到测试按键上即可。

  • StartServer()。
HiLog.info(LABEL_LOG, "StartServer run");

NetManager netManager = NetManager.getInstance(null);

if (!netManager.hasDefaultNet()) {
HiLog.error(LABEL_LOG,
"netManager.hasDefaultNet() failed");

return;
}
NetHandle netHandle = netManager.getDefaultNet();
DatagramSocket socket = null;
// 通过Socket绑定来进行数据传输
try {
HiLog.info(LABEL_LOG, "wait receive data");
//通过getLocalIpAddress()快速获取本机的IP地址
InetAddress address = netHandle.getByName(getLocalIpAddress());
//端口号+主机地址
socket = new DatagramSocket(10006, address);
netHandle.bindSocket(socket);
/*至此绑定Socket结束*/
HiLog.info(LABEL_LOG, "绑定成功");
/*监听函数*/
byte[] buffer = new byte[1024];
DatagramPacket response = new DatagramPacket(buffer,
buffer.length);
while (true) {
//接收数据
socket.receive(response);
int len = response.getLength();
HiLog.info(LABEL_LOG, "接收成功");
//将数据打印到屏幕上
s = new String(buffer, StandardCharsets.UTF_8).substring(0,
len);
//一个textfield组件
text.setText(s);
HiLog.info(LABEL_LOG, "receive data: " + s);
}
} catch (IOException e) {
HiLog.error(LABEL_LOG, "rev IOException: ");
}
}
  • sendMessage()。
NetManager netManager = NetManager.getInstance(null);
if (!netManager.hasDefaultNet()) {
HiLog.error(LABEL_LOG,
"netManager.hasDefaultNet() failed");
return;
}
NetHandle netHandle = netManager.getDefaultNet();
// 通过Socket绑定来进行数据传输
DatagramSocket socket = null;
try {
//从textfield组件获取用户输入的对端ip地址
HOST = iptf.getText();
InetAddress address = netHandle.getByName(HOST);
socket = new DatagramSocket();
netHandle.bindSocket(socket);
/*至此 已绑定对端Socket*/
//从一个textfield组件获取用户输入的要发送的信息。
String data = new String(sendtf.getText());
//这里默认还是发送至对端的10006端口
DatagramPacket request = new DatagramPacket(data.getBytes(
StandardCharsets.UTF_8), data.length(),
address, PORT);
// buffer赋值
// 发送数据
socket.send(request);
HiLog.info(LABEL_LOG, "send data: " + data);
} catch (IOException e) {
HiLog.error(LABEL_LOG, "send IOException: ");
} finally {
if (null != socket) {
}
}
  • getlocalip()。
private String getLocalIpAddress() {
WifiDevice wifiDevice = WifiDevice.getInstance(getContext());
Optional<IpInfo> ipInfo = wifiDevice.getIpInfo();
int ip = ipInfo.get().getIpAddress();
return (ip & 0xFF) + "." + ((ip >> 8) & 0xFF) + "." + ((ip >> 16) & 0xFF) + "." + (ip >> 24 & 0xFF);
}

至此,接收信息和发送信息的函数都编写完了。但并没有结束,这样的函数并不能跑在UI线程上,我们必须让其在其他线程上运作,那必须请出我们最爱的EventRunner.

3、编写Mythread类

​EventRunner传送门​​。

package com.example.hoop.util;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
public class Mythread {
public static void inUI(Runnable runnable) {
//返回主线程
EventRunner runner = EventRunner.getMainEventRunner();
EventHandler eventHandler = new EventHandler(runner);
eventHandler.postSyncTask(runnable);
}
public static void inBG(Runnable runnable) {
EventRunner runner = EventRunner.create(true);
EventHandler eventHandler = new EventHandler(runner);
//投递任务,我们的Socket函数应该投递于此。
eventHandler.postTask(runnable, 0, EventHandler.Priority.IMMEDIATE);
}
}
  • 将任务投递给EventRunner。

只需要将刚刚的两个主要函数投递就行了。

private void sendMessage() {
Mythread.inBG(new Runnable() {
@Override
public void run() {
NetManager netManager = NetManager.getInstance(null);
if (!netManager.hasDefaultNet()) {
HiLog.error(LABEL_LOG,"netManager.hasDefaultNet() failed");
return;
}
NetHandle netHandle = netManager.getDefaultNet();
// 通过Socket绑定来进行数据传输
DatagramSocket socket = null;
try {
//从textfield组件获取用户输入的对端ip地址
HOST=iptf.getText();
InetAddress address = netHandle.getByName(HOST);
socket = new DatagramSocket();
netHandle.bindSocket(socket);
/*至此 已绑定对端Socket*/
//从一个textfield组件获取用户输入的要发送的信息。
String data = new String(sendtf.getText());
//这里默认还是发送至对端的10006端口
DatagramPacket request = new DatagramPacket(data.getBytes(StandardCharsets.UTF_8), data.length(), address, PORT);
// buffer赋值
// 发送数据
socket.send(request);
HiLog.info(LABEL_LOG,"send data: " + data);
} catch (IOException e) {
HiLog.error(LABEL_LOG,"send IOException: ");
} finally {
if (null != socket) {

}
}
}
});
}
private void StartServer() {
Mythread.inBG(new Runnable() {
@Override
public void run() {
HiLog.info(LABEL_LOG,"StartServer run");
NetManager netManager = NetManager.getInstance(null);
if (!netManager.hasDefaultNet()) {
HiLog.error(LABEL_LOG,"netManager.hasDefaultNet() failed");
return;
}
NetHandle netHandle = netManager.getDefaultNet();
DatagramSocket socket = null;
// 通过Socket绑定来进行数据传输
try {
HiLog.info(LABEL_LOG,"wait receive data");
//通过getLocalIpAddress()快速获取本机的IP地址
InetAddress address = netHandle.getByName(getLocalIpAddress());
//端口号+主机地址
socket = new DatagramSocket(10006, address);
netHandle.bindSocket(socket);
/*至此绑定Socket结束*/
HiLog.info(LABEL_LOG,"绑定成功");
/*监听函数*/
byte[] buffer = new byte[1024];
DatagramPacket response = new DatagramPacket(buffer, buffer.length);
while(true){
//接收数据
socket.receive(response);
int len = response.getLength();
HiLog.info(LABEL_LOG,"接收成功");
//将数据打印到屏幕上
s = new String(buffer, StandardCharsets.UTF_8).substring(0, len);
Mythread.inUI(new Runnable() {
@Override
public void run() {
//一个textfield组件
text.setText(s);
}
});
HiLog.info(LABEL_LOG,"receive data: " + s);
}
} catch (IOException e) {
HiLog.error(LABEL_LOG,"rev IOException: " );
}
}
});

}

三、OpenHarmony侧

1、新建工程,编写测试页面

#夏日挑战赛# 【FFH】OpenHarmony与HarmonyOS实现信息交流(一)-开源基础软件社区

  • index.hml。
<div class="container"> 
<text class="title">
{{ title }}
</text>
<!-- <div style="width: 30%;height: 30%;background-color: blueviolet;">-->
<!-- </div>-->
<!-- <input type="text" id="localip" placeholder="输入本机IP"-->
<!-- @change="newlocalip">-->
<!-- </input>-->
<text style="width: 300px;height: 70px;">
本机IP{{getIpAddress()}}
</text>
<button type="capsule" style="width: 300px;height: 70px;" onclick="creatScoket"> 点击创建 </button>
<input id="remoteip" placeholder="输入服务器IP" @change="newremoteip" />
<button type="capsule" style="width: 300px;height: 70px;margin-top: 5%;" onclick="sendMessage"> 点击连接 </button>
<input placeholder="输入需要发送的信息" type="text" enterkeytype="done" @change="newMessage" />
</div>

2、编写Socket功能

​OpenHarmony-Socket​​。

import socket from '@ohos.net.socket';
import wifi from '@ohos.wifi';
export default {
data: {
title: "等待新的消息...",
tcp: socket.constructTCPSocketInstance(),
remoteip:'none',
localip:'none',
msg:"A NEW WORLD",
udp:socket.constructUDPSocketInstance(),
},
onInit() {
this.getIpAddress();
this.creatScoket();
this.title="暂无新消息"
},
//创建udpSocket 默认端口10006
creatScoket: async function(){
this.udp.bind({address: this.getIpAddress(), port: 10006, family: 1}, err => {
if (err) {
console.info('bind fail');
this.title='bind fail'
return;
}
this.title='bind success';
console.info('bind success');
})
// this.tcp.bind({address: this.localip, port: 10006,family: 1}, err => {
// if (err) {
// console.log('bind fail');
// this.title='bind fail';
// return;
// }
// this.title='bind success';
// console.log('bind success');
// })
//监听收到的信息 打印到屏幕上
this.udp.on('message', value => {
let buffer = value.message;
let dataView = new DataView(buffer);
let str = "";
for (let i = 0;i < dataView.byteLength; ++i) {
str += String.fromCharCode(dataView.getUint8(i))
}
this.title =str;
});
},
sendMessage: async function(){
// let promise1 = this.udp.connect({ address: {address: this.remoteip, port: 10006, family: 1} , timeout: 6000});
// promise1.then(() => {
// console.log('connect success');
// let promise2 =this.udp.send({
// data:this.msg
// });
// promise2.then(() => {
// console.log('send success');
// }).catch(err => {
// console.log('send fail');
// });
// }).catch(err => {
// this.title='connect fail';
// console.log('connect fail');
// });
//发送信息
let promise = this.udp.send({
data:this.msg,
address: {
address:this.remoteip,
port:10006,
family:1
}
});
promise.then(() => {
this.title='send success';
console.info('send success');
}).catch(err => {
this.title='send fail'
console.info('send fail');
});
},
newlocalip(e){
this.localip = e.value;
this.title = e.value;
},
newremoteip(e){
this.remoteip = e.value;
},
newMessage(e){
this.msg=e.value;
this.title=e.value;
},
//获取本机ip地址
getIpAddress(){
let ip=wifi.getIpInfo().ipAddress;
this.localip = (ip >> 24 & 0xFF)+"."+ ((ip >> 16) & 0xFF)+"."+((ip >> 8) & 0xFF)+"."+(ip & 0xFF);
},
}

四、测试

这里为了便于测试,我们最好下载一个网络调试助手.

网络调试助手

1、结果

  • OpenHarmony侧

#夏日挑战赛# 【FFH】OpenHarmony与HarmonyOS实现信息交流(一)-开源基础软件社区

  • HarmonyOS侧

#夏日挑战赛# 【FFH】OpenHarmony与HarmonyOS实现信息交流(一)-开源基础软件社区

  • OpenHarmony&HarmonyOS 联动

#夏日挑战赛# 【FFH】OpenHarmony与HarmonyOS实现信息交流(一)-开源基础软件社区

五、结语

实现了OpenHarmony与HarmonyOS的简单通讯后,应用开发,软硬件联动都有了更多的可能性。目前可能存在一些稳定性,不完整性问题,未来两侧基础功能不断完善之后,将会变得更有趣也更好用。如有明显错误,希望读者能够积极提出,我会尽力完善。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​​。

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2022-06-12 06:48:34

2022-06-22 09:19:55

HDC鸿蒙ADB命令

2022-04-07 15:28:16

HarmonyOS鸿蒙操作系统

2022-05-24 15:06:57

AbilityeTS FA鸿蒙

2022-06-15 16:16:21

分布式数据库鸿蒙

2021-10-11 08:37:14

2022-04-15 14:31:02

鸿蒙操作系统

2022-04-07 14:33:31

操作系统鸿蒙HarmonyOS

2022-04-18 10:37:01

鸿蒙操作系统开发工具

2022-06-06 10:55:51

本地服务鸿蒙

2022-04-20 20:28:40

HDF 驱动框架鸿蒙操作系统

2022-05-11 15:08:52

驱动开发系统移植

2022-06-07 10:33:29

Camera组件鸿蒙

2022-06-15 11:02:40

网络安全运营

2022-06-09 14:40:14

系统移植鸿蒙

2022-03-10 14:45:23

HarmonyAPI操作系统

2022-05-24 15:55:37

避障小车华为

2022-03-28 15:40:34

harmony鸿蒙操作系统

2022-06-13 14:18:39

电源管理子系统耗电量服务

2022-02-24 16:15:16

OpenHarmon鸿蒙OpenEuler

同话题下的热门内容

HarmonyOS - HDC命令与ADB命令使用对比OHOS构建自定义服务实战啃论文俱乐部—数据密集型应用内存压缩HarmonyOS - 自定义组件之计时器HarmonyOS - 方舟开发框架ArkUI 流光按钮效果基于OpenHarmony3.1的购物车应用的实现OpenHarmony3.1-Ace-Formcomponent源码解析OpenHarmony HiSysEvent打点调用实践(L2)

编辑推荐

HarmonyOS 2.0鸿蒙第二期开发者Beta公测申请指南HarmonyOS LYEVK-3861开发板播放《蜜雪冰城》鸿蒙HarmonyOS分布式软总线:构建低时延、高带宽的多设备虚拟网络华为HarmonyOS的强势突围: 直面物联网迷宫的蓄力进击鸿蒙HarmonyOS2.0发布会现场回忆录
我收藏的内容
点赞
收藏

51CTO技术栈公众号