• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_INFO39此权限级别为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_INFO199此权限级别为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_INFO219此权限级别为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)