1# 网络连接管理 2 3## 简介 4 5网络连接管理提供管理网络一些基础能力,包括WiFi/蜂窝/Ethernet等多网络连接优先级管理、网络质量评估、订阅默认/指定网络连接状态变化、查询网络连接信息、DNS解析等功能。 6 7> **说明:** 8> 为了保证应用的运行效率,大部分API调用都是异步的,对于异步调用的API均提供了callback和Promise两种方式,以下示例均采用promise函数,更多方式可以查阅[API参考](../reference/apis-network-kit/js-apis-net-connection.md)。 9 10## 基本概念 11 12- 网络生产者:数据网络的提供方,比如WiFi、蜂窝、Ethernet等。 13- 网络消费者:数据网络的使用方,比如应用或系统服务。 14- 网络探测:检测网络有效性,避免将网络从可用网络切换到不可用网络。内容包括绑定网络探测、DNS探测、HTTP探测及HTTPS探测。 15- 网络优选:处理多网络共存时选择最优网络。在网络状态、网络信息及评分发生变化时被触发。 16 17## 约束 18 19- 开发语言:JS 20- 本模块首批接口从API version 8开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 21 22## 场景介绍 23 24网络连接管理的典型场景有: 25 26- 接收指定网络的状态变化通知 27- 获取所有注册的网络 28- 根据数据网络查询网络的连接信息 29- 使用对应网络解析域名,获取所有IP 30 31以下分别介绍具体开发方式。 32 33## 接口说明 34 35完整的JS API说明以及实例代码请参考:[网络连接管理](../reference/apis-network-kit/js-apis-net-connection.md)。 36 37| 接口名 | 描述 | 38| ---- | ---- | 39| getDefaultNet(callback: AsyncCallback\<NetHandle>): void; |获取一个含有默认网络的netId的NetHandle对象,使用callback回调 | 40| <!--DelRow--> getGlobalHttpProxy(callback: AsyncCallback\<HttpProxy>): void;| 获取网络的全局代理设置,使用callback回调 | 41| <!--DelRow--> setGlobalHttpProxy(httpProxy: HttpProxy, callback: AsyncCallback\<void>): void;| 设置网络全局Http代理配置信息,使用callback回调 | 42| setAppHttpProxy(httpProxy: HttpProxy): void;| 设置网络应用级Http代理配置信息 | 43| getAppNet(callback: AsyncCallback\<NetHandle>): void;| 获取一个App绑定的包含了网络netId的NetHandle对象,使用callback回调 | 44| setAppNet(netHandle: NetHandle, callback: AsyncCallback\<void>): void;| 绑定App到指定网络,绑定后的App只能通过指定网络访问外网。使用callback回调 | 45| getDefaultNetSync(): NetHandle; |使用同步方法获取默认激活的数据网络。可以使用getNetCapabilities去获取网络的类型、拥有的能力等信息。| 46| hasDefaultNet(callback: AsyncCallback\<boolean>): void; |检查默认数据网络是否被激活,使用callback回调 | 47| getAllNets(callback: AsyncCallback\<Array\<NetHandle>>): void;| 获取所处于连接状态的网络的NetHandle对象列表,使用callback回调 | 48| getConnectionProperties(netHandle: NetHandle, callback: AsyncCallback\<ConnectionProperties>): void; |查询netHandle对应的网络的连接信息,使用callback回调 | 49| getNetCapabilities(netHandle: NetHandle, callback: AsyncCallback\<NetCapabilities>): void; |获取netHandle对应的网络的能力信息,使用callback回调 | 50| isDefaultNetMetered(callback: AsyncCallback\<boolean>): void; |检查当前网络上的数据流量使用是否被计量,使用callback方式作为异步方法 | 51| reportNetConnected(netHandle: NetHandle, callback: AsyncCallback\<void>): void;| 向网络管理报告网络处于可用状态,调用此接口说明应用程序认为网络的可用性(ohos.net.connection.NetCap.NET_CAPABILITY_VAILDATED)与网络管理不一致。使用callback回调 | 52| reportNetDisconnected(netHandle: NetHandle, callback: AsyncCallback\<void>): void;| 向网络管理报告网络处于不可用状态,调用此接口说明应用程序认为网络的可用性(ohos.net.connection.NetCap.NET_CAPABILITY_VAILDATED)与网络管理不一致。使用callback回调 | 53| getAddressesByName(host: string, callback: AsyncCallback\<Array\<NetAddress>>): void; |使用对应网络解析域名,获取所有IP,使用callback回调 | 54| <!--DelRow--> enableAirplaneMode(callback: AsyncCallback\<void>): void; | 设置网络为飞行模式,使用callback回调 | 55| <!--DelRow--> disableAirplaneMode(callback: AsyncCallback\<void>): void;| 关闭网络飞行模式,使用callback回调 | 56| createNetConnection(netSpecifier?: NetSpecifier, timeout?: number): NetConnection; | 返回一个NetConnection对象,netSpecifier指定关注的网络的各项特征,timeout是超时时间(单位是毫秒),netSpecifier是timeout的必要条件,两者都没有则表示关注默认网络 | 57| bindSocket(socketParam: TCPSocket \| UDPSocket, callback: AsyncCallback\<void>): void; | 将TCPSocket或UDPSockett绑定到当前网络,使用callback回调 | 58| getAddressesByName(host: string, callback: AsyncCallback\<Array\<NetAddress>>): void; |使用对应网络解析域名,获取所有IP,使用callback回调 | 59| getAddressByName(host: string, callback: AsyncCallback\<NetAddress>): void; |使用对应网络解析域名,获取一个IP,调用callbac | 60| on(type: 'netAvailable', callback: Callback\<NetHandle>): void; |订阅网络可用事件 | 61| on(type: 'netCapabilitiesChange', callback: Callback\<NetCapabilityInfo\>): void; |订阅网络能力变化事件 | 62| on(type: 'netConnectionPropertiesChange', callback: Callback\<{ netHandle: NetHandle, connectionProperties: ConnectionProperties }>): void; |订阅网络连接信息变化事件 | 63| on(type: 'netBlockStatusChange', callback: Callback<{ netHandle: NetHandle, blocked: boolean }>): void; |订阅网络阻塞状态事件,使用callback方式作为异步方法 | 64| on(type: 'netLost', callback: Callback\<NetHandle>): void; |订阅网络丢失事件 | 65| on(type: 'netUnavailable', callback: Callback\<void>): void; |订阅网络不可用事件 | 66| register(callback: AsyncCallback\<void>): void; |订阅指定网络状态变化的通知 | 67| unregister(callback: AsyncCallback\<void>): void; |取消订阅默认网络状态变化的通知 | 68 69## 接收指定网络的状态变化通知 70 711. 声明接口调用所需要的权限:ohos.permission.GET_NETWORK_INFO。 72此权限级别为normal,在申请权限前,请保证符合[权限使用的基本原则](../security/AccessToken/app-permission-mgmt-overview.md#权限使用的基本原则)。然后参考[访问控制-声明权限](../security/AccessToken/declare-permissions.md)声明对应权限。 73 741. 从@kit.NetworkKit中导入connection命名空间。 75 762. 调用createNetConnection方法,指定网络能力、网络类型和超时时间(可选,如不传入代表默认网络;创建不同于默认网络时可通过指定这些参数完成),创建一个NetConnection对象。 77 783. 调用该对象的on()方法,传入type和callback,订阅关心的事件。 79 804. 调用该对象的register()方法,订阅指定网络状态变化的通知。 81 825. 当网络可用时,会收到netAvailable事件的回调;当网络不可用时,会收到netUnavailable事件的回调。 83 846. 当不使用该网络时,可以调用该对象的unregister()方法,取消订阅。 85 86```ts 87// 引入包名 88import { connection } from '@kit.NetworkKit'; 89import { BusinessError } from '@kit.BasicServicesKit'; 90 91let netSpecifier: connection.NetSpecifier = { 92 netCapabilities: { 93 // 假设当前默认网络是WiFi,需要创建蜂窝网络连接,可指定网络类型为蜂窝网 94 bearerTypes: [connection.NetBearType.BEARER_CELLULAR], 95 // 指定网络能力为Internet 96 networkCap: [connection.NetCap.NET_CAPABILITY_INTERNET] 97 }, 98}; 99 100// 指定超时时间为10s(默认值为0) 101let timeout = 10 * 1000; 102 103// 创建NetConnection对象 104let conn = connection.createNetConnection(netSpecifier, timeout); 105 106// 订阅指定网络状态变化的通知 107conn.register((err: BusinessError, data: void) => { 108 console.log(JSON.stringify(err)); 109}); 110 111// 订阅事件,如果当前指定网络可用,通过on_netAvailable通知用户 112conn.on('netAvailable', ((data: connection.NetHandle) => { 113 console.log("net is available, netId is " + data.netId); 114})); 115 116// 订阅事件,如果当前指定网络不可用,通过on_netUnavailable通知用户 117conn.on('netUnavailable', ((data: void) => { 118 console.log("net is unavailable, data is " + JSON.stringify(data)); 119})); 120 121// 当不使用该网络时,可以调用该对象的unregister()方法,取消订阅 122conn.unregister((err: BusinessError, data: void) => { 123}); 124``` 125 126## 监控默认网络变化并主动重建网络连接 127 128根据当前网络状态及网络质量情况,默认网络可能会发生变化,如: 1291. 在WiFi弱信号的情况下,默认网络可能会切换到蜂窝网络。 1302. 在蜂窝网络状态差的情况下,默认网络可能会切换到WiFi。 1313. 关闭WiFi后,默认网络可能会切换到蜂窝网络。 1324. 关闭蜂窝网络后,默认网络可能会切换到WiFi。 1335. 在WiFi弱信号的情况下,默认网络可能会切换到其他WiFi(存在跨网情况)。 1346. 在蜂窝网络状态差的情况下,默认网络可能会切换到其他蜂窝(存在跨网情况)。 135 136本节旨在介绍监控默认网络的变化后,应用报文能够快速迁移到新默认网络上,具体做法如下。 137 138### 监控默认网络变化 139 140```ts 141import { connection } from '@kit.NetworkKit'; 142 143async function test() { 144 const netConnection = connection.createNetConnection(); 145 146 /* 监听默认网络改变 */ 147 netConnection.on('netAvailable', (data: connection.NetHandle) => { 148 console.log(JSON.stringify(data)); 149 }); 150} 151``` 152 153### 默认网络变化后重新建立网络连接 154 155#### 原网络连接使用http模块建立网络连接 156 157如果您使用了http模块建立网络连接,由于该模块没有提供Close接口用于关闭Socket,在切换默认网络并建立新的网络连接后原有Socket不会立即关闭。因此请切换使用Remote Communication Kit建立网络连接。 158 159#### 原网络连接使用Remote Communication Kit建立网络连接 160 161```ts 162import { rcp } from '@kit.RemoteCommunicationKit'; 163import { connection } from '@kit.NetworkKit'; 164import { BusinessError } from '@kit.BasicServicesKit'; 165 166let session = rcp.createSession(); 167 168async function useRcp() { 169 /* 建立rcp请求 */ 170 try { 171 const request = await session.get('https://www.example.com'); 172 console.info(request.statusCode.toString()); 173 } catch (e) { 174 console.error(e.code.toString()); 175 } 176} 177 178async function rcpTest() { 179 const netConnection = connection.createNetConnection(); 180 netConnection.on('netAvailable', async (netHandle: connection.NetHandle) => { 181 /* 发生默认网络切换,重新建立session */ 182 session.close(); 183 session = rcp.createSession(); 184 useRcp(); 185 }); 186 try { 187 netConnection.register(() => { 188 }); 189 useRcp(); 190 } catch (e) { 191 console.error(e.code.toString()); 192 } 193} 194``` 195 196#### 原网络连接使用Socket模块建立连接 197 198```ts 199import { connection, socket } from '@kit.NetworkKit'; 200import { BusinessError } from '@kit.BasicServicesKit'; 201 202let sock: socket.TCPSocket = socket.constructTCPSocketInstance(); 203 204async function useSocket() { 205 let tcpConnectOptions: socket.TCPConnectOptions = { 206 address: { 207 address: '192.168.xx.xxx', 208 port: 8080 209 }, 210 timeout: 6000 211 } 212 213 /* 建立socket连接 */ 214 sock.connect(tcpConnectOptions, (err: BusinessError) => { 215 if (err) { 216 console.error('connect fail'); 217 return; 218 } 219 console.log('connect success'); 220 221 /* 通过socket发送数据 */ 222 let tcpSendOptions: socket.TCPSendOptions = { 223 data: 'Hello, server!' 224 } 225 sock.send(tcpSendOptions).then(() => { 226 console.log('send success'); 227 }).catch((err: BusinessError) => { 228 console.error('send fail'); 229 }); 230 }) 231} 232 233async function socketTest() { 234 const netConnection = connection.createNetConnection(); 235 netConnection.on('netAvailable', async (netHandle: connection.NetHandle) => { 236 console.log('default network changed'); 237 await sock.close(); 238 sock = socket.constructTCPSocketInstance(); 239 useSocket(); 240 }); 241 try { 242 netConnection.register(() => { 243 }); 244 useSocket(); 245 } catch (e) { 246 console.error(e.code.toString()); 247 } 248} 249``` 250 251#### 原网络连接使用Socket Library建立网络连接 252 253请在监控到默认网络变化后关闭原有Socket并重新建立Socket连接。 254 255## 获取所有注册的网络 256 2571. 声明接口调用所需要的权限:ohos.permission.GET_NETWORK_INFO。 258此权限级别为normal,在申请权限前,请保证符合[权限使用的基本原则](../security/AccessToken/app-permission-mgmt-overview.md#权限使用的基本原则)。然后参考[访问控制-声明权限](../security/AccessToken/declare-permissions.md)声明对应权限。 259 2602. 从@kit.NetworkKit中导入connection命名空间。 261 2623. 调用getAllNets方法,获取所有处于连接状态的网络列表。 263 264```ts 265// 引入包名 266import { connection } from '@kit.NetworkKit'; 267import { BusinessError } from '@kit.BasicServicesKit'; 268 269// 构造单例对象 270export class GlobalContext { 271 public netList: connection.NetHandle[] = []; 272 private constructor() {} 273 private static instance: GlobalContext; 274 private _objects = new Map<string, Object>(); 275 276 public static getContext(): GlobalContext { 277 if (!GlobalContext.instance) { 278 GlobalContext.instance = new GlobalContext(); 279 } 280 return GlobalContext.instance; 281 } 282 283 getObject(value: string): Object | undefined { 284 return this._objects.get(value); 285 } 286 287 setObject(key: string, objectClass: Object): void { 288 this._objects.set(key, objectClass); 289 } 290} 291 292// 获取所有处于连接状态的网络列表 293connection.getAllNets().then((data: connection.NetHandle[]) => { 294 console.info("Succeeded to get data: " + JSON.stringify(data)); 295 if (data) { 296 GlobalContext.getContext().netList = data; 297 } 298}); 299``` 300 301## 根据数据网络查询网络的能力信息及连接信息 302 3031. 声明接口调用所需要的权限:ohos.permission.GET_NETWORK_INFO。 304此权限级别为normal,在申请权限前,请保证符合[权限使用的基本原则](../security/AccessToken/app-permission-mgmt-overview.md#权限使用的基本原则)。然后参考[访问控制-声明权限](../security/AccessToken/declare-permissions.md)声明对应权限。 305 3062. 从@kit.NetworkKit中导入connection命名空间。 307 3083. 通过调用getDefaultNet方法,获取默认的数据网络(NetHandle);或者通过调用getAllNets方法,获取所有处于连接状态的网络列表(Array\<NetHandle>)。 309 3104. 调用getNetCapabilities方法,获取NetHandle对应网络的能力信息。能力信息包含了网络类型(蜂窝网络、Wi-Fi网络、以太网网络等)、网络具体能力等网络信息。 311 3125. 调用getConnectionProperties方法,获取NetHandle对应网络的连接信息。 313 314```ts 315import { connection } from '@kit.NetworkKit'; 316import { BusinessError } from '@kit.BasicServicesKit'; 317 318// 构造单例对象 319export class GlobalContext { 320 public netList: connection.NetHandle[] = []; 321 public netHandle: connection.NetHandle|null = null; 322 private constructor() {} 323 private static instance: GlobalContext; 324 private _objects = new Map<string, Object>(); 325 326 public static getContext(): GlobalContext { 327 if (!GlobalContext.instance) { 328 GlobalContext.instance = new GlobalContext(); 329 } 330 return GlobalContext.instance; 331 } 332 333 getObject(value: string): Object | undefined { 334 return this._objects.get(value); 335 } 336 337 setObject(key: string, objectClass: Object): void { 338 this._objects.set(key, objectClass); 339 } 340} 341 342// 调用getDefaultNet方法,获取默认的数据网络(NetHandle) 343connection.getDefaultNet().then((data:connection.NetHandle) => { 344 if (data.netId == 0) { 345 // 当前无默认网络时,获取的netHandler的netid为0,属于异常情况,需要额外处理 346 return; 347 } 348 if (data) { 349 console.info("getDefaultNet get data: " + JSON.stringify(data)); 350 GlobalContext.getContext().netHandle = data; 351 // 获取netHandle对应网络的能力信息。能力信息包含了网络类型、网络具体能力等网络信息 352 connection.getNetCapabilities(GlobalContext.getContext().netHandle).then( 353 (data: connection.NetCapabilities) => { 354 console.info("getNetCapabilities get data: " + JSON.stringify(data)); 355 // 获取网络类型(bearerTypes) 356 let bearerTypes: Set<number> = new Set(data.bearerTypes); 357 let bearerTypesNum = Array.from(bearerTypes.values()); 358 for (let item of bearerTypesNum) { 359 if (item == 0) { 360 // 蜂窝网 361 console.log(JSON.stringify("BEARER_CELLULAR")); 362 } else if (item == 1) { 363 // Wi-Fi网络 364 console.log(JSON.stringify("BEARER_WIFI")); 365 } else if (item == 3) { 366 // 以太网网络 367 console.log(JSON.stringify("BEARER_ETHERNET")); 368 } 369 } 370 371 // 获取网络具体能力(networkCap) 372 let itemNumber : Set<number> = new Set(data.networkCap); 373 let dataNumber = Array.from(itemNumber.values()); 374 for (let item of dataNumber) { 375 if (item == 0) { 376 // 表示网络可以访问运营商的MMSC(Multimedia Message Service,多媒体短信服务)发送和接收彩信 377 console.log(JSON.stringify("NET_CAPABILITY_MMS")); 378 } else if (item == 11) { 379 // 表示网络流量未被计费 380 console.log(JSON.stringify("NET_CAPABILITY_NOT_METERED")); 381 } else if (item == 12) { 382 // 表示该网络应具有访问Internet的能力,该能力由网络提供者设置 383 console.log(JSON.stringify("NET_CAPABILITY_INTERNET")); 384 } else if (item == 15) { 385 // 表示网络不使用VPN(Virtual Private Network,虚拟专用网络) 386 console.log(JSON.stringify("NET_CAPABILITY_NOT_VPN")); 387 } else if (item == 16) { 388 // 表示该网络访问Internet的能力被网络管理成功验证,该能力由网络管理模块设置 389 console.log(JSON.stringify("NET_CAPABILITY_VALIDATED")); 390 } 391 } 392 }) 393 } 394}); 395 396// 获取netHandle对应网络的连接信息。连接信息包含了链路信息、路由信息等 397connection.getConnectionProperties(GlobalContext.getContext().netHandle).then((data: connection.ConnectionProperties) => { 398 console.info("getConnectionProperties get data: " + JSON.stringify(data)); 399}) 400 401// 调用getAllNets,获取所有处于连接状态的网络列表(Array<NetHandle>) 402connection.getAllNets().then((data: connection.NetHandle[]) => { 403 console.info("getAllNets get data: " + JSON.stringify(data)); 404 if (data) { 405 GlobalContext.getContext().netList = data; 406 407 let itemNumber : Set<connection.NetHandle> = new Set(GlobalContext.getContext().netList); 408 let dataNumber = Array.from(itemNumber.values()); 409 for (let item of dataNumber) { 410 // 循环获取网络列表每个netHandle对应网络的能力信息 411 connection.getNetCapabilities(item).then((data: connection.NetCapabilities) => { 412 console.info("getNetCapabilities get data: " + JSON.stringify(data)); 413 }) 414 415 // 循环获取网络列表每个netHandle对应的网络的连接信息 416 connection.getConnectionProperties(item).then((data: connection.ConnectionProperties) => { 417 console.info("getConnectionProperties get data: " + JSON.stringify(data)); 418 }) 419 } 420 } 421}) 422``` 423 424## 使用对应网络解析域名,获取所有IP 425 4261. 声明接口调用所需要的权限:ohos.permission.INTERNET 427此权限级别为normal,在申请权限前,请保证符合[权限使用的基本原则](../security/AccessToken/app-permission-mgmt-overview.md#权限使用的基本原则)。然后参考[访问控制-声明权限](../security/AccessToken/declare-permissions.md)声明对应权限。 428 4292. 从@kit.NetworkKit中导入connection命名空间。 430 4313. 调用getAddressesByName方法,使用默认网络解析主机名以获取所有IP地址。 432 433```ts 434// 引入包名 435import { connection } from '@kit.NetworkKit'; 436import { BusinessError } from '@kit.BasicServicesKit'; 437 438// 使用默认网络解析主机名以获取所有IP地址 439connection.getAddressesByName("xxxx").then((data: connection.NetAddress[]) => { 440 console.info("Succeeded to get data: " + JSON.stringify(data)); 441}); 442``` 443