0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

鸿蒙的网络管理功能你们知道有多厉害吗

OpenHarmony技术社区 来源:鸿蒙技术社区 作者:Buty9147 2021-10-11 14:26 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

本示例演示了如何使用网络管理模块相关接口,演示了以下功能:

  • 功能 1:使用默认网络,打开连接,发送 HTTP 请求。

  • 功能 2:统计指定 UID 的上行/下行流量。

  • 功能 3:使用 Socket 方式实现不同设备间通信。此功能需要打开 WIFI,并且通信的设备连接相同的 WIFI 组成局域网。操作上,先启动服务端,再启动客户端,然后从客户端发送消息,查看服务端是否收到消息。

  • 功能 4:HTTP 缓存的使用,创建缓存,供下一次请求使用,减少数据流量和加载时间。

注意,需要以下权限:

  • ohos.permission.GET_NETWORK_INFO:获取网络连接信息。

  • ohos.permission.SET_NETWORK_INFO:修改网络连接状态。

  • ohos.permission.INTERNET:允许程序打开网络套接字,进行网络连接。

详情见官方文档,网络管理开发概述:
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/connectivity-net-overview-0000000000029978

搭建环境

安装 DevEco Studio,详情请参考DevEco Studio 下载:
https://developer.harmonyos.com/cn/develop/deveco-studio

设置 DevEco Studio 开发环境,DevEco Studio 开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用。

可以根据如下两种情况来配置开发环境:

  • 如果可以直接访问 Internet,只需进行下载 HarmonyOS SDK 操作。

  • 如果网络不能直接访问 Internet,需要通过代理服务器才可以访问,请参考配置开发环境
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/environment_config-0000001052902427

下载源码后,使用 DevEco Studio 打开项目,模拟器运行即可。真机运行需要将 config.json 中的 buddleName 修改为自己的,如果没有请到 AGC 上进行配置。

参见《使用模拟器进行调试

https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404

代码结构

①代码结构

如下图:

3576ed16-2a47-11ec-82a8-dac502259ad0.png

②相关文件介绍

核心类:

  • HttpURLConnection.java //支持 HTTP 特定功能的 URLConnection

  • URLConnection.java //URL 连接

  • URL.java //指向万维网上“资源”的指针

  • NetStatusCallback.java //网络状态的回调类,出现可用网络触发onAvailable函数

  • DataFlowStatistics.java //该类提供查询指定蜂窝网络、应用和网卡的整体流量统计和流量统计的接口

  • DatagramSocket.java //此类表示用于发送和接收数据报包的套接字。

  • DatagramPacket.java //数据报包

  • WifiDevice.java //该类提供 Wi-Fi 管理接口

  • NetManager.java //提供接口来管理和使用数据网络

  • NetHandle.java //数据网络

  • InetAddress.java //网络 IP 地址

  • HttpResponseCache.java //该类缓存 HTTP 和 HTTPS 响应以供重用

自定义的类:

  • ThreadPoolUtil.java //线程池工具类

  • MainAbilitySlice.java //主页面

  • NetRequestSlice.java //网络请求&流量统计 功能页

  • SocketClientSlice.java //Socket 客户端

  • SocketServerSlice.java //Socket 服务端

  • HttpCacheSlice.java //HTTP 缓存功能页

页面布局:

  • http_cache_slice.xml //HTTP 缓存示例页

  • net_request.slice.xml //HTTP 请求页面

  • socket_client_slice.xml //Socket 通信客户端页

  • socket_server_slice.xml //Socket 通信服务端页

  • main_ability_slice.xml //主页面

实例讲解

①界面布局

如下图:

35f45a26-2a47-11ec-82a8-dac502259ad0.png

369ebc1e-2a47-11ec-82a8-dac502259ad0.png

371711dc-2a47-11ec-82a8-dac502259ad0.png

②后台代码

NetRequestSlice.java 网络请求&流量统计功能

a.初始化网络管理对象 NetManager。
//初始化网络管理对象
netManager=NetManager.getInstance(null);

b.通过线程池获取一个新线程处理进行连接请求,获取默认数据网络的时候需要 ohos.permission.GET_NETWORK_INFO 权限。

//用线程池的取一个新线程处理
ThreadPoolUtil.submit(()->{
HiLog.debug(LABEL_LOG,"%{public}s","ThreadPoolUtilsubmit");
//获取默认的数据网络,wifi和流量都关闭时,netId==0,其它时netId=390/391,musthavetheohos.permission.GET_NETWORK_INFOpermission
NetHandlenetHandle=netManager.getDefaultNet();
//接收默认数据网络的状态更改的回调
netManager.addDefaultNetStatusCallback(callback);

//netManager.setAppNet(netHandle);

//支持 HTTP 特定功能的 URLConnection。
HttpURLConnectionconnection=null;
//输出流
try(ByteArrayOutputStreamoutputStream=newByteArrayOutputStream()){
//请求的URL
StringurlString=inputText.getText();

URLurl=newURL(urlString);
//使用netHandle打开URL连接,不使用代理
URLConnectionurlConnection=netHandle.openConnection(url,java.net.Proxy.NO_PROXY);
HiLog.debug(LABEL_LOG,"%{public}s","netHandleopenConnection");
//强转换类型
if(urlConnectioninstanceofHttpURLConnection){
connection=(HttpURLConnection)urlConnection;
}
//请求类型
connection.setRequestMethod("GET");
//连接
connection.connect();
//流量统计
trafficDataStatistics(false);

try(InputStreaminputStream=urlConnection.getInputStream()){
byte[]cache=newbyte[2*1024];
intlen=inputStream.read(cache);
while(len!=-1){
//
outputStream.write(cache,0,len);
len=inputStream.read(cache);
}
}catch(IOExceptione){
HiLog.error(LABEL_LOG,"%{public}s","netRequestinnerIOException");
}
//返回结果
Stringresult=newString(outputStream.toByteArray());

//UI显示
getUITaskDispatcher().asyncDispatch(()->outText.setText(result));
//统计完毕
trafficDataStatistics(true);

}catch(IOExceptione){
HiLog.error(LABEL_LOG,"%{public}s","netRequestIOException");
}
});

c.按照应用 ID,进行数据流量统计,在发送请求前获取一次,在请求完成后获取一次。

gitee 代码中这个地方有一处笔误,tx 代表上行流量,rx 代表下行流量才对。

详情见官方文档说明《流量统计》:
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/connectivity-net-traffic-0000000000045998

/**
*按照应用ID,进行数据流量统计
*
*@paramisStart
*/
privatevoidtrafficDataStatistics(booleanisStart){
intuid=0;
try{
//根据给定的包名称和用户 ID 获取应用程序 UID。
uid=getBundleManager().getUidByBundleName(getBundleName(),0);
}catch(RemoteExceptione){
HiLog.error(LABEL_LOG,"%{public}s","trafficDataStatisticsRemoteException");
}
if(isStart){
//获取指定UID的下行流量。
rx=DataFlowStatistics.getUidRxBytes(uid);
//获取指定UID的上行流量。
tx=DataFlowStatistics.getUidTxBytes(uid);
}else{
rx=DataFlowStatistics.getUidRxBytes(uid)-rx;
tx=DataFlowStatistics.getUidTxBytes(uid)-tx;

//设置UI显示
getUITaskDispatcher().asyncDispatch(()->statisticsText.setText(
"TrafficDataStatistics:"+System.lineSeparator()
+"Receivetraffic:"+rx+System.lineSeparator()
+"Senttraffic:"+tx));
}
}
}

SocketClientSlice.java/SocketServerSlice.java Socket 客户端/服务端

实现 Socket 通信,是要客户端和服务端的,服务端在指定网卡上监听指定端口,客户端向指定 IP 指定端口发送数据,实现通信。

a.Socket 服务端开启监听,等待接收数据。

//监听端口
privatestaticfinalintPORT=8888;

/**
*启动socket服务监听
*
*@paramcomponent
*/
privatevoidstartServer(Componentcomponent){
HiLog.debug(LABEL_LOG,"startServer");

//线程池获取新线程处理
ThreadPoolUtil.submit(()->{
//在指定端口开启监听
try(DatagramSocketsocket=newDatagramSocket(PORT)){
//数据报包
DatagramPacketpacket=newDatagramPacket(newbyte[255],255);
//死循环接收数据
while(true){
//接收数据
socket.receive(packet);

//通过专有线程同步设置要显示接收到的数据
getUITaskDispatcher().syncDispatch(()->outText.setText(
"Receiveamessagefrom:"+packet.getAddress().getHostAddress()
+System.lineSeparator()+"onport"+packet.getPort()
+System.lineSeparator()+"message:"+newString(
packet.getData()).substring(0,packet.getLength())
));
packet.setLength(255);

//延迟一下,留出处理数据的时间
Thread.sleep(1000);
}
}catch(IOException|InterruptedExceptione){
e.printStackTrace();
HiLog.error(LABEL_LOG,"%{public}s","StartServerIOException|InterruptedException"+e);
}
});
}


/**
*获取服务器端IP地址,显示给客户端发送消息使用
*
*@return
*/
privateStringgetLocationIpAddress(){
HiLog.debug(LABEL_LOG,"getLocationIpAddress");
//提供接口来管理 Wi-Fi。
WifiDevicewifiDevice=WifiDevice.getInstance(this);
HiLog.debug(LABEL_LOG,"wifiDevice:"+wifiDevice);
//WifiLinkedInfo提供有关 Wi-Fi 连接的信息。
OptionallinkedInfo=wifiDevice.getLinkedInfo();
HiLog.debug(LABEL_LOG,"linkedInfo:"+linkedInfo);
//获取IP地址
intip=linkedInfo.get().getIpAddress();
HiLog.debug(LABEL_LOG,"ip:"+ip);
return(ip&0xFF)+"."+((ip>>8)&0xFF)+"."+((ip>>16)&0xFF)+"."+(ip>>24&0xFF);
}

b.Socket 客户端发送数据,等待接收数据。

初始化 NetManager 对象→new 一个 DatagramSocket获取当前数据网络 NetHandle获取服务端的 IP 地址对象 InetAddressDatagramSocket 绑定到 NetHandlenew 一个数据报包 DatagramPacket发送数据。

//通信端口
privatestaticfinalintPORT=8888;


/**
*发送网络请求
*@paramcomponent
*/
privatevoidnetRequest(Componentcomponent){
HiLog.debug(LABEL_LOG,"netRequest");
//启动新线程
ThreadPoolUtil.submit(()->{
//初始化网络管理对象
NetManagernetManager=NetManager.getInstance(null);

//检查默认数据网络是否已激活。
if(!netManager.hasDefaultNet()){
return;
}
//new套接字
try(DatagramSocketsocket=newDatagramSocket()){
//获取当前数据网络
NetHandlenetHandle=netManager.getDefaultNet();

//获取服务端的IP地址
InetAddressaddress=netHandle.getByName(inputText.getText());
//将套接字绑定到当前网络
netHandle.bindSocket(socket);
byte[]buffer="I'mfromClient".getBytes();
//数据包
DatagramPacketrequest=newDatagramPacket(buffer,buffer.length,address,PORT);
//发送数据
socket.send(request);
HiLog.debug(LABEL_LOG,"sendsocket");
}catch(IOExceptione){
e.printStackTrace();
HiLog.error(LABEL_LOG,"%{public}s","netRequestIOException"+e);
}
});
}

HttpCacheSlice.java HTTP 缓存功能

应用重复打开一个相同网页时,可以优先从缓存文件里读取内容,从而减少数据流量,降低设备功耗,提升应用性能。

问:如何设置优先从缓存文件里读取内容?答:不用额外设置,自动的~~设置缓存,需要考虑缓存位置和缓存大小。

a.初始化缓存 install。

/**
*开启缓存
*开启后自动缓存数据,不需要手动处理
*/
privatevoidinitCache(Componentcomponent){
//默认的缓存目录
FilehttpCacheDir=newFile(this.getCacheDir(),"http");
//缓存大小
longhttpCacheSize=10*1024*1024;
try{
//配置缓存目录及最大缓存空间
HttpResponseCache.install(httpCacheDir,httpCacheSize);
HiLog.debug(LABEL_LOG,"%{public}s","initCache,cacheinstalled["+httpCacheDir+"]");
}catch(IOExceptione){
HiLog.error(LABEL_LOG,"%{public}s","initCacheIOException");
}
}

b.保存缓存,将缓存写入文件系统 flush。

/**
*将缓存写入文件系统,防止缓存丢失
*/
privatevoidflushCache(Componentcomponent){
HiLog.debug(LABEL_LOG,"%{public}s","flushCache");
try{
//获取缓存对象
HttpResponseCachecache=HttpResponseCache.getInstalled();
HiLog.debug(LABEL_LOG,"%{public}s","cache:"+cache);
if(cache!=null){
try{
//将缓存写入文件系统,如果cacheisclosed会报错//java.lang.IllegalStateException:cacheisclosed
cache.flush();
getUITaskDispatcher().syncDispatch(()->{
//图片加载时间,测试缓存和不缓存的差别
duration.setText("cacheflushsuccess");
});
HiLog.debug(LABEL_LOG,"%{public}s","cacheflush");
}catch(IOExceptione){
HiLog.error(LABEL_LOG,"%{public}s","onStopIOException");
}
}
}catch(IllegalStateExceptione){
e.printStackTrace();
}
}

c.禁用缓存并删除其中的数据 delete。
/**
*禁用缓存并删除其中的数据
*/
privatevoiddeleteCache(Componentcomponent){
HiLog.debug(LABEL_LOG,"%{public}s","deleteCache");
//获取缓存对象
HttpResponseCachecache=HttpResponseCache.getInstalled();
HiLog.debug(LABEL_LOG,"%{public}s","cache:"+cache);
if(cache!=null){
try{
//禁用缓存并删除其中的数据。
cache.delete();
image.setPixelMap(null);
HiLog.debug(LABEL_LOG,"%{public}s","cachedelete");
}catch(IOExceptione){
HiLog.error(LABEL_LOG,"%{public}s","onStopIOException");
}

}
}

/**
*测试请求
*
*@paramcomponent
*/
privatevoidstartRequest(Componentcomponent){
HiLog.debug(LABEL_LOG,"%{public}s","startRequest");
ThreadPoolUtil.submit(()->{
try{
longstartTime=System.currentTimeMillis();
HiLog.debug(LABEL_LOG,"%{public}s","startTime:"+startTime);
//请求URL
URLurl=newURL(inputText.getText());
URLConnectionurlConnection=url.openConnection();
HiLog.debug(LABEL_LOG,"%{public}s","openConnection");
//判断连接类型
if(urlConnectioninstanceofHttpURLConnection){
HiLog.debug(LABEL_LOG,"%{public}s","urlConnection");
HttpURLConnectionconnection=(HttpURLConnection)urlConnection;
HiLog.debug(LABEL_LOG,"%{public}s","connect:"+connection);
//连接
connection.connect();
HiLog.debug(LABEL_LOG,"%{public}s","connected");
//连接结果
if(connection.getResponseCode()==HttpURLConnection.HTTP_OK){
HiLog.debug(LABEL_LOG,"%{public}s","HTTP_OK");
//描述图像数据源选项,例如包括表示为 image/png 的图像格式。
ImageSource.SourceOptionssrcOpts=newImageSource.SourceOptions();
ImageSourceimageSource=ImageSource.create(connection.getInputStream(),srcOpts);
//以像素矩阵的形式提供图像。
PixelMappixelMap=imageSource.createPixelmap(null);
HiLog.debug(LABEL_LOG,"%{public}s","pixelMap:"+pixelMap);
//专有线程同步设置图片显示
getUITaskDispatcher().syncDispatch(()->{
image.setPixelMap(pixelMap);
//图片加载时间,测试缓存和不缓存的差别
duration.setText(String.valueOf(System.currentTimeMillis()-startTime)+"ms");
});
HiLog.debug(LABEL_LOG,"%{public}s","setPixelMap");
HiLog.debug(LABEL_LOG,"%{public}s","endTime:"+(System.currentTimeMillis()-startTime));
}
HiLog.debug(LABEL_LOG,"%{public}s","finish");
//关闭连接
connection.disconnect();
}
}catch(Exceptione){
HiLog.error(LABEL_LOG,"%{public}s","initCacheException"+e);
getUITaskDispatcher().syncDispatch(()->{
//图片加载时间,测试缓存和不缓存的差别
duration.setText("cacheisclosed,pleaseopencache");
});
}
});
}

总结说明

①两种打开网络连接的方式:

URLConnectionurlConnection=url.openConnection();

//使用netHandle打开URL连接,不使用代理
URLConnectionurlConnection=netHandle.openConnection(url,java.net.Proxy.NO_PROXY);

②未开启缓存情况下,发送请求的时长在 400-2000ms 之间,开启后,需要点击两次发送请求,时长维持在 90-200ms 左右。

③禁用并清除缓存 delete/close 后,在没有再次开启缓存前,无法发送请求。这个操作官方文档注释写的是 “结束时关闭缓存”。

完整代码

附件直接下载:

https://harmonyos.51cto.com/resource/1270
编辑:jq
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 网络管理
    +关注

    关注

    0

    文章

    129

    浏览量

    29426
  • HTTP
    +关注

    关注

    0

    文章

    539

    浏览量

    35646
  • 数据包
    +关注

    关注

    0

    文章

    270

    浏览量

    25689
  • 代码
    +关注

    关注

    30

    文章

    4983

    浏览量

    74558
  • 鸿蒙系统
    +关注

    关注

    183

    文章

    2642

    浏览量

    70247

原文标题:鸿蒙的网络管理功能,十分强悍!

文章出处:【微信号:gh_834c4b3d87fe,微信公众号:OpenHarmony技术社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    IEC104能源管理平台什么功能哪些推荐?

    IEC104协议凭借其在电力系统中高效、稳定的数据传输特性,已成为能源管理领域的“通用语言”。一个成熟的IEC104能源管理平台,通常具备以下核心功能源数据采集与协议转换(兼容IE
    的头像 发表于 05-14 16:05 110次阅读
    IEC104能源<b class='flag-5'>管理</b>平台<b class='flag-5'>有</b>什么<b class='flag-5'>功能</b>?<b class='flag-5'>有</b>哪些推荐?

    硅到底小?

    知道硅到底小;CPU 并不比 Wii 上的百老汇芯片大,但功能却无限强大,哈哈。
    发表于 03-25 06:51

    艺开放平台鸿蒙智能体版本管理

    智能体的版本管理功能,包括查看、回退到历史版本。版本记录中包括智能体上下架及撤回审核时的版本。 查看历史版本 点击智能体编排页右上角【版本记录】图标可查看版本记录,点击某个版本可以查看该版本智能体
    发表于 02-27 19:18

    以龙企招为例,浅谈鸿蒙应用开发者激励计划 2025 参与心得

    生活、企业期望及兴趣小组等板块,助力求职者快速了解企业文化;职位页面涵盖社会招聘、校园招聘、实习生招聘等类型岗位入口,支持精准的职位搜索;“我的” 页面则集成了收藏、投递记录、简历管理等常用服务
    发表于 12-12 10:17

    想体验鸿蒙生态,该怎么获取鸿蒙开发板?哪些途径?

    如何快速上手体验鸿蒙生态? 想体验鸿蒙生态,该怎么获取鸿蒙开发板?哪些途径?
    发表于 11-29 08:40

    淘宝规格SKU管理接口

    ​  在电商系统中,规格SKU(Stock Keeping Unit,库存量单位)管理是核心功能之一,尤其对于淘宝这类大型平台。它允许商家为同一商品定义不同规格组合(如颜色、尺寸、材质),每个组合
    的头像 发表于 10-10 15:32 718次阅读
    淘宝<b class='flag-5'>多</b>规格SKU<b class='flag-5'>管理</b>接口

    管理型 vs 非管理型,工业网络如何选择以太网交换机?

    在工业网络建设中,很多人会纠结该选管理型还是非管理型交换机。非管理型交换机即插即用、价格实惠,适合小型场景;而管理型交换机
    的头像 发表于 08-25 15:37 1106次阅读
    <b class='flag-5'>管理</b>型 vs 非<b class='flag-5'>管理</b>型,工业<b class='flag-5'>网络</b>如何选择以太网交换机?

    Modbus能源监测管理平台什么功能

    Modbus能源监测管理平台以 实时数据采集、设备监控与远程控制、数据分析与优化、系统集成与互操作性 为核心功能,结合安全防护与灵活部署能力,为能源管理提供全面支持。具体功能如下: 一
    的头像 发表于 07-24 16:09 655次阅读

    已收藏!你需要知道的57个常用树莓派命令!

    初次使用树莓派并不总是那么容易,因为你可能还没有使用命令行的习惯。然而,终端命令是必不可少的,而且通常比通过图形用户界面(GUI)操作更高效。那么,哪些重要的命令是你应该知道的呢?相当
    的头像 发表于 07-23 18:36 1371次阅读
    已收藏!你需要<b class='flag-5'>知道</b>的57个常用树莓派命令!

    智能装备物联网远程管理平台是什么?什么功能

    预警、远程维护、数据分析与决策支持等功能,帮助企业提高设备运行效率、降低运维成本并提升整体生产管理水平。 平台核心功能详解 设备接入与统一管理
    的头像 发表于 07-10 15:03 2157次阅读

    鸿蒙开发API9 到 API12,哪些不同

    上传图片等与图片相关的功能测试,而API12的模拟器中虽然图库,但是并没有图片,需要使用一些“特殊手段”才能导入图片测试相关功能 ​​ 五、包的区别 API9中,很多能力的引入大部分都是ohos开头
    发表于 06-29 22:47

    网络电机伺服系统监控终端设计

    较少,只能实现基本的系统状态监控和报警等功能。同时,需要现场对每个电机驱动器参数逐一进行设定,不便于系统的使用和调试\"1。因此,针对基于CAN总线的电机伺服系统,设计一种实时性高、运行
    发表于 06-23 07:15

    鸿蒙5开发宝藏案例分享---优化应用包体积大小问题

    ?** 鸿蒙包体积优化实战:藏在官方文档里的宝藏技巧!** 大家好呀~我是你们鸿蒙开发小伙伴!今天在翻官方文档时,发现了一个超实用的「包体积优化」案例宝藏库!这些技巧明明能大幅提升应用体验,却很
    发表于 06-13 10:09

    设备综合管理平台哪些功能特点

    设备综合管理平台是面向工业、能源、建筑、医疗等行业的数字化工具,旨在通过全生命周期管理、数据驱动决策、智能化运维等手段,提升设备利用率、降低运维成本、保障生产安全。以下是其核心功能特点的详细解析
    的头像 发表于 06-07 15:55 965次阅读

    鸿蒙5开发宝藏案例分享---自由流转的拖拽屏联动

    ? 【干货预警】鸿蒙开发宝藏案例大揭秘!手把手教你玩转常用功能**?** 大家好呀~,今天在扒拉鸿蒙文档的时候,突然发现官方竟然藏了一堆超实用的开发案例! ?** 之前总觉得鸿蒙生态资
    发表于 06-03 18:50