1# 管理网络连接 2<!--Kit: Network Kit--> 3<!--Subsystem: Communication--> 4<!--Owner: @wmyao_mm--> 5<!--Designer: @guo-min_net--> 6<!--Tester: @tongxilin--> 7<!--Adviser: @zhang_yixin13--> 8 9## 简介 10 11网络连接管理提供管理网络一些基础能力,包括WiFi/蜂窝/Ethernet等多网络连接优先级管理、网络质量评估、订阅默认/指定网络连接状态变化、查询网络连接信息、DNS解析等功能。 12 13> **说明:** 14> 15> 为了保证应用的运行效率,大部分API调用都是异步的,对于异步调用的API,均提供了callback和Promise两种方式,以下示例均采用promise函数,更多方式可以查阅[API参考](../reference/apis-network-kit/js-apis-net-connection.md)。 16 17## 基本概念 18 19- 网络生产者:数据网络的提供方。例如WiFi、蜂窝、Ethernet等。 20- 网络消费者:数据网络的使用方。例如应用或系统服务。 21- 网络探测:检测网络有效性,避免将网络从可用网络切换到不可用网络。包括绑定网络探测、DNS探测、HTTP探测及HTTPS探测。 22- 网络优选:处理多网络共存时选择最优网络。在网络状态、网络信息及评分发生变化时被触发。 23- 默认网络:默认路由所在的网络。 24 25## 场景介绍 26 27网络连接管理的典型场景如下所示。 28 29- 接收指定网络的状态变化通知。 30- 获取所有注册的网络。 31- 查询默认网络或者指定网络的连接信息。 32- 使用默认网络解析域名,获取所有IP。 33 34具体开发方式介绍如下。 35 36## 接收指定网络的状态变化通知 37 381. 声明接口调用所需要的权限:ohos.permission.GET_NETWORK_INFO。 39此权限级别为normal,在申请权限前,请保证符合[权限使用的基本原则](../security/AccessToken/app-permission-mgmt-overview.md#权限使用的基本原则)。然后参考[访问控制-声明权限](../security/AccessToken/declare-permissions.md)声明对应权限。 40 412. 从@kit.NetworkKit中导入connection命名空间。 42 43 ```ts 44 // 引入包名。 45 import { connection } from '@kit.NetworkKit'; 46 import { BusinessError } from '@kit.BasicServicesKit'; 47 ``` 48 493. 调用[createNetConnection](../reference/apis-network-kit/js-apis-net-connection.md#connectioncreatenetconnection)方法,指定网络能力、网络类型和超时时间(可选,如不传入代表默认网络;创建不同于默认网络时可通过指定这些参数完成),创建一个NetConnection对象。 50 51 ```ts 52 let netSpecifier: connection.NetSpecifier = { 53 netCapabilities: { 54 // 假设当前默认网络是WiFi,需要创建蜂窝网络连接,可指定网络类型为蜂窝网。 55 bearerTypes: [connection.NetBearType.BEARER_CELLULAR], 56 // 指定网络能力为Internet。 57 networkCap: [connection.NetCap.NET_CAPABILITY_INTERNET] 58 }, 59 }; 60 61 // 指定超时时间为10s(默认值为0)。 62 let timeout = 10 * 1000; 63 64 // 创建NetConnection对象。 65 let conn = connection.createNetConnection(netSpecifier, timeout); 66 ``` 67 684. 调用该对象的[register()](../reference/apis-network-kit/js-apis-net-connection.md#register)方法,订阅指定网络状态变化的通知。当网络可用时,会收到netAvailable事件的回调;当网络不可用时,会收到netUnavailable事件的回调。 69 70 ```ts 71 // 订阅指定网络状态变化的通知。 72 conn.register((err: BusinessError, data: void) => { 73 console.log(JSON.stringify(err)); 74 }); 75 ``` 76 775. 调用该对象的[on()](../reference/apis-network-kit/js-apis-net-connection.md#onnetavailable)方法,传入type和callback,订阅关心的事件。 78 79 ```ts 80 // 订阅事件,如果当前指定网络可用,通过on_netAvailable通知用户。 81 conn.on('netAvailable', ((data: connection.NetHandle) => { 82 console.log("net is available, netId is " + data.netId); 83 })); 84 85 // 订阅事件,如果当前指定网络不可用,通过on_netUnavailable通知用户。 86 conn.on('netUnavailable', ((data: void) => { 87 console.log("net is unavailable, data is " + JSON.stringify(data)); 88 })); 89 ``` 906. 当不使用该网络时,可以调用该对象的[unregister()](../reference/apis-network-kit/js-apis-net-connection.md#unregister)方法,取消订阅。 91 92 ```ts 93 // 当不使用该网络时,可以调用该对象的unregister()方法,取消订阅。 94 conn.unregister((err: BusinessError, data: void) => { 95 }); 96 ``` 97 98## 监控默认网络变化并主动重建网络连接 99 100根据当前网络状态及网络质量情况,默认网络可能会发生变化,如下所示。 1011. 在WiFi弱信号的情况下,默认网络可能会切换到蜂窝网络。 1022. 在蜂窝网络状态差的情况下,默认网络可能会切换到WiFi。 1033. 关闭WiFi后,默认网络可能会切换到蜂窝网络。 1044. 关闭蜂窝网络后,默认网络可能会切换到WiFi。 1055. 在WiFi弱信号的情况下,默认网络可能会切换到其他WiFi(存在跨网情况)。 1066. 在蜂窝网络状态差的情况下,默认网络可能会切换到其他蜂窝(存在跨网情况)。 107 108本节旨在介绍监控默认网络的变化后,应用报文能够快速迁移到新默认网络上,具体做法如下。 109 110### 监控默认网络变化 111 112```ts 113import { connection } from '@kit.NetworkKit'; 114 115const netConnection = connection.createNetConnection(); 116// 监听默认网络改变。 117netConnection.on('netAvailable', (data: connection.NetHandle) => { 118 console.log(JSON.stringify(data)); 119}) 120``` 121 122### 默认网络变化后重新建立网络连接 123 124<!--RP1--> 125 126<!--RP1End--> 127 128**原网络连接使用Socket模块建立连接** 129```ts 130import { connection, socket } from '@kit.NetworkKit'; 131import { BusinessError } from '@kit.BasicServicesKit'; 132 133// 创建socket对象。 134let sock: socket.TCPSocket = socket.constructTCPSocketInstance(); 135 136function useSocket() { 137 let netAddress: socket.NetAddress = { 138 address: '192.168.xx.xxx', 139 port: 8080 140 } 141 let tcpConnectOptions: socket.TCPConnectOptions = { 142 address: netAddress, 143 timeout: 6000 144 } 145 146 // 建立socket连接。 147 sock.connect(tcpConnectOptions, (err: BusinessError) => { 148 if (err) { 149 console.error('connect fail'); 150 return; 151 } 152 console.log('connect success'); 153 let tcpSendOptions: socket.TCPSendOptions = { 154 data: 'Hello, server!' 155 } 156 socketSend(tcpSendOptions); 157 }) 158} 159 160// 通过socket发送数据。 161function socketSend(tcpSendOptions: socket.TCPSendOptions) { 162 sock.send(tcpSendOptions).then(() => { 163 console.log('send success'); 164 }).catch((err: BusinessError) => { 165 console.error('send fail'); 166 }); 167} 168 169 170function socketTest() { 171 const netConnection = connection.createNetConnection(); 172 // 网络切换会导致网络发生中断,原socket失效,故需重新建立socket。 173 netConnection.on('netAvailable', (netHandle: connection.NetHandle) => { 174 console.info("default network changed: " + JSON.stringify(netHandle)); 175 sock.close(); 176 sock = socket.constructTCPSocketInstance(); 177 // 通过socket发送数据。 178 useSocket(); 179 }); 180 181 // 订阅指定网络状态变化的通知。 182 netConnection.register((error: BusinessError) => { 183 if (error) { 184 console.error("register fail: " + JSON.stringify(error)); 185 } else { 186 console.info("register success"); 187 } 188 }); 189} 190``` 191 192**原网络连接使用Socket Library建立网络连接** 193 194监控到默认网络变化后关闭原有Socket并重新建立Socket连接。 195 196## 获取所有注册的网络 197 1981. 声明接口调用所需要的权限:ohos.permission.GET_NETWORK_INFO。 199此权限级别为normal,在申请权限前,请保证符合[权限使用的基本原则](../security/AccessToken/app-permission-mgmt-overview.md#权限使用的基本原则)。然后参考[访问控制-声明权限](../security/AccessToken/declare-permissions.md)声明对应权限。 200 2012. 示例代码 202 ```ts 203 // 从@kit.NetworkKit中导入connection命名空间。 204 import { connection } from '@kit.NetworkKit'; 205 import { BusinessError } from '@kit.BasicServicesKit'; 206 207 // 调用getAllNets方法,获取所有处于连接状态的网络列表。 208 connection.getAllNets().then((data: connection.NetHandle[]) => { 209 console.info("Succeeded to get data: " + JSON.stringify(data)); 210 if (data) { 211 GlobalContext.getContext().netList = data; 212 } 213 }); 214 ``` 215 216## 查询默认网络或者指定网络的连接信息 217 2181. 声明接口调用所需要的权限:ohos.permission.GET_NETWORK_INFO。 219此权限级别为normal,在申请权限前,请保证符合[权限使用的基本原则](../security/AccessToken/app-permission-mgmt-overview.md#权限使用的基本原则)。然后参考[访问控制-声明权限](../security/AccessToken/declare-permissions.md)声明对应权限。 2202. 查询默认网络或指定网络连接信息代码示例 221 222 通过调用[getDefaultNet](../reference/apis-network-kit/js-apis-net-connection.md#connectiongetdefaultnet)方法,获取默认的数据网络(NetHandle);调用[getNetCapabilities](../reference/apis-network-kit/js-apis-net-connection.md#connectiongetnetcapabilities)方法,获取该NetHandle对应网络的能力信息。能力信息包含了网络类型(蜂窝网络、Wi-Fi网络、以太网网络等)、网络具体能力等网络信息。也可以调用[getConnectionProperties](../reference/apis-network-kit/js-apis-net-connection.md#connectiongetconnectionproperties)方法,获取该NetHandle对应网络的连接信息。 223 224 225 ```ts 226 // 从@kit.NetworkKit中导入connection命名空间。 227 import { connection } from '@kit.NetworkKit'; 228 import { BusinessError } from '@kit.BasicServicesKit'; 229 230 function getDefaultNetsInfo() { 231 let netHandleInfo:connection.NetHandle|null = null; 232 // 调用getDefaultNet方法,获取默认的数据网络(NetHandle)。 233 connection.getDefaultNet().then((data:connection.NetHandle) => { 234 if (data.netId == 0) { 235 console.log("don't have defaultNet"); 236 // 当前无默认网络时,获取的netHandler的netid为0,属于异常情况,需要额外处理。 237 return; 238 } 239 if (data) { 240 console.info("getDefaultNet get data: " + JSON.stringify(data)); 241 // 获取netHandle对应网络的能力信息。能力信息包含了网络类型、网络具体能力等网络信息。 242 netHandleInfo = data; 243 connection.getNetCapabilities(netHandleInfo).then((data: connection.NetCapabilities) => { 244 console.info("getNetCapabilities get data: " + JSON.stringify(data)); 245 // 获取网络类型(bearerTypes)。 246 let bearerTypes: Set<number> = new Set(data.bearerTypes); 247 let bearerTypesNum = Array.from(bearerTypes.values()); 248 for (let item of bearerTypesNum) { 249 if (item == 0) { 250 // 蜂窝网络。 251 console.log(JSON.stringify("BEARER_CELLULAR")); 252 } else if (item == 1) { 253 // Wi-Fi网络。 254 console.log(JSON.stringify("BEARER_WIFI")); 255 } else if (item == 3) { 256 // 以太网网络。 257 console.log(JSON.stringify("BEARER_ETHERNET")); 258 } 259 } 260 261 // 获取网络具体能力(networkCap)。 262 let itemNumber : Set<number> = new Set(data.networkCap); 263 let dataNumber = Array.from(itemNumber.values()); 264 for (let item of dataNumber) { 265 if (item == 0) { 266 // 表示网络可以访问运营商的MMSC(Multimedia Message Service,多媒体短信服务)发送和接收彩信。 267 console.log(JSON.stringify("NET_CAPABILITY_MMS")); 268 } else if (item == 11) { 269 // 表示网络流量未被计费。 270 console.log(JSON.stringify("NET_CAPABILITY_NOT_METERED")); 271 } else if (item == 12) { 272 // 表示该网络应具有访问Internet的能力,该能力由网络提供者设置。 273 console.log(JSON.stringify("NET_CAPABILITY_INTERNET")); 274 } else if (item == 15) { 275 // 表示网络不使用VPN(Virtual Private Network,虚拟专用网络)。 276 console.log(JSON.stringify("NET_CAPABILITY_NOT_VPN")); 277 } else if (item == 16) { 278 // 表示该网络访问Internet的能力被网络管理成功验证,该能力由网络管理模块设置。 279 console.log(JSON.stringify("NET_CAPABILITY_VALIDATED")); 280 } 281 } 282 }) 283 } 284 }); 285 286 // 获取netHandle对应的网络的连接信息。 287 connection.getConnectionProperties(netHandleInfo).then((data: connection.ConnectionProperties) => { 288 console.info("getConnectionProperties get data: " + JSON.stringify(data)); 289 }) 290 } 291 ``` 2923. 查询所有网络连接信息代码示例 293 294 通过调用[getAllNets](../reference/apis-network-kit/js-apis-net-connection.md#connectiongetallnets)方法,获取所有处于连接状态的网络列表(Array\<NetHandle>)。然后遍历获取到的NetHandle数组,分别调用[getNetCapabilities](../reference/apis-network-kit/js-apis-net-connection.md#connectiongetnetcapabilities)方法,获取该NetHandle对应网络的能力信息,能力信息包含了网络类型(蜂窝网络、Wi-Fi网络、以太网网络等)、网络具体能力等网络信息。也可以调用[getConnectionProperties](../reference/apis-network-kit/js-apis-net-connection.md#connectiongetconnectionproperties)方法,获取该NetHandle对应网络的连接信息。 295 296 ```ts 297 // 从@kit.NetworkKit中导入connection命名空间。 298 import { connection } from '@kit.NetworkKit'; 299 import { BusinessError } from '@kit.BasicServicesKit'; 300 301 function getAllNetsInfo() { 302 // 调用getAllNets,获取所有处于连接状态的网络列表(Array<NetHandle>)。 303 connection.getAllNets().then((data: connection.NetHandle[]) => { 304 console.info("getAllNets get data: " + JSON.stringify(data)); 305 if (data) { 306 let itemNumber : Set<connection.NetHandle> = new Set(data); 307 let dataNumber = Array.from(itemNumber.values()); 308 for (let item of dataNumber) { 309 // 循环获取网络列表每个netHandle对应网络的能力信息。 310 connection.getNetCapabilities(item).then((data: connection.NetCapabilities) => { 311 console.info("getNetCapabilities get data: " + JSON.stringify(data)); 312 }) 313 314 // 循环获取网络列表每个netHandle对应的网络的连接信息。 315 connection.getConnectionProperties(item).then((data: connection.ConnectionProperties) => { 316 console.info("getConnectionProperties get data: " + JSON.stringify(data)); 317 }) 318 } 319 } 320 }) 321 } 322 ``` 323 324## 判断默认网络是否可以访问互联网 325 326如果应用需要检查当前连接的网络是否可以访问互联网,可参考以下步骤进行判断: 327 3281. 声明接口调用所需要的权限:ohos.permission.GET_NETWORK_INFO 329此权限级别为normal,在申请权限前,请保证符合[权限使用的基本原则](../security/AccessToken/app-permission-mgmt-overview.md#权限使用的基本原则)。然后参考[访问控制-声明权限](../security/AccessToken/declare-permissions.md)声明对应权限。 330 3312. 代码示例 332 333 调用[getDefaultNetSync](../reference/apis-network-kit/js-apis-net-connection.md#connectiongetdefaultnetsync9)方法,获取当前默认网络的netHandle,netHandle有效的情况下,调用[getNetCapabilitiesSync](../reference/apis-network-kit/js-apis-net-connection.md#connectiongetnetcapabilitiessync10)方法,获取NetHandle对应网络的能力信息,根据获取到的能力信息,判断networkCap数组中的值判断网络是否可用。 334 NET_CAPABILITY_CHECKING_CONNECTIVITY表示在进行连通性判断的过程中,当不处于连通性判断过程中,且networkCap数组中包含NET_CAPABILITY_VALIDATED表示网络连通性校验通过,可以访问互联网。 335 336 ```ts 337 // 从@kit.NetworkKit中导入connection命名空间。 338 import { connection } from '@kit.NetworkKit'; 339 import { BusinessError } from '@kit.BasicServicesKit'; 340 341 // 获取默认激活的数据网络。 342 let netHandle = connection.getDefaultNetSync(); 343 if (!netHandle || netHandle.netId === 0) { 344 console.error("getDefaultNetSync fail"); 345 } else { 346 console.info("default network: " + JSON.stringify(netHandle)); 347 // 获取netHandle对应网络的能力信息。 348 let netCapabilities = connection.getNetCapabilitiesSync(netHandle); 349 let cap = netCapabilities.networkCap; 350 console.info("network capabilities: " + JSON.stringify(netCapabilities)); 351 // 判断网络是否可以访问互联网。 352 if (cap?.includes(connection.NetCap.NET_CAPABILITY_CHECKING_CONNECTIVITY)) { 353 // 正在验证网络连通性,请稍后重试。 354 console.info("default network is checking, please try again later"); 355 } else { 356 if (cap?.includes(connection.NetCap.NET_CAPABILITY_VALIDATED)) { 357 // 网络连通性验证成功,当前默认网络可以访问互联网。 358 console.info("default network is validated"); 359 } else { 360 // 网络连通性验证失败,当前默认网络不可以访问互联网。 361 console.info("default network is not validated"); 362 } 363 } 364 } 365 ``` 366 367## 使用默认网络解析域名,获取所有IP 368 3691. 声明接口调用所需要的权限:ohos.permission.GET_NETWORK_INFO 370此权限级别为normal,在申请权限前,请保证符合[权限使用的基本原则](../security/AccessToken/app-permission-mgmt-overview.md#权限使用的基本原则)。然后参考[访问控制-声明权限](../security/AccessToken/declare-permissions.md)声明对应权限。 371 3722. 代码示例 373 374 调用[getAddressesByName](../reference/apis-network-kit/js-apis-net-connection.md#connectiongetaddressesbyname)方法,使用默认网络解析主机名以获取所有IP地址。 375 ```ts 376 // 从@kit.NetworkKit中导入connection命名空间。 377 import { connection } from '@kit.NetworkKit'; 378 import { BusinessError } from '@kit.BasicServicesKit'; 379 // 使用默认网络解析主机名以获取所有IP地址。 380 connection.getAddressesByName("xxxx").then((data: connection.NetAddress[]) => { 381 console.info("Succeeded to get data: " + JSON.stringify(data)); 382 }); 383 ``` 384 385## 相关实例 386 387针对网络连接的开发,有以下相关实例可供参考: 388 389- [NetConnection_Manage_case(网络连接管理)](https://gitcode.com/openharmony/applications_app_samples/tree/master/code/DocsSample/NetWork_Kit/NetWorkKit_NetManager/NetConnection_Manage_case)