# 使用DNS解析域名

#### 场景介绍

域名解析（DNS, Domain Name System）功能允许应用将主机名（域名）转换为IP地址。支持中文字符与ASCII码之间的转换、获取指定域名的IP地址列表、以及在不同网络环境下进行域名解析。

当前支持功能如下：

| 功能名称 | 功能描述 | 开始支持的版本 |
| --- | --- | --- |
| Unicode与ASCII转换 | 支持中文域名与ASCII编码之间的相互转换 | API version 23 |
| 获取主机名的所有IP地址 | 使用当前默认网络解析主机名，获取所有IP地址 | API version 23 |
| 指定IP类型解析主机名 | 使用当前默认网络，指定IP类型（IPv4/IPv6）解析主机名 | API version 23 |
| 指定网络连接解析主机名 | 使用特定网络连接NetHandle解析主机名 | API version 23 |

#### DNS解析支持中文域名转码

从API version 23开始，DNS解析支持中文转码，支持中文域名与ASCII编码之间的相互转换。

在本文档的示例中，资源文件中hostName需修改成一个实际的中文域名。

完整示例代码见：DNS\_case

1.  导入所需文件。
    
    ```
    import { connection } from '@kit.NetworkKit';
    import { BusinessError } from '@kit.BasicServicesKit';
    import { hilog } from '@kit.PerformanceAnalysisKit';
    ```
    
2.  初始化数据成员。
    
    ```
    @State hostVal: string = '';     // 转码之后的主机名
    @State ipResult: string = '';    // 获取的IP地址结果
    private hostName: string = '';   // 初始主机名
    ```
    
3.  获取资源文件中hostName值并赋值。
    
    ```
    aboutToAppear() {
      this.hostName =
        (this.getUIContext().getHostContext() as Context).resourceManager.getStringSync($r('app.string.hostName').id);
    }
    ```
    
4.  创建网络地址解析函数，将域名转换为IP地址，isChange为是否将域名转码为ASCII编码的标识。
    
    ```
    getAddressName(isChange: boolean) {
      this.ipResult = '';
      connection.getDefaultNet().then((netHandle: connection.NetHandle) => {
        if (netHandle.netId === 0) {
          // 当前没有已连接的网络时，netHandler的netId为0，属于异常场景。可根据实际情况添加处理机制。
          return;
        }
        if (isChange) {
          this.hostVal = connection.getDnsAscii(this.hostName);
        } else {
          this.hostVal = '';
        }
        netHandle.getAddressByName(isChange ? this.hostVal : this.hostName,
          (error: BusinessError, data: connection.NetAddress) => {
            if (error) {
              this.ipResult = `Failed to get address. Code:${error.code}, message:${error.message}`;
              hilog.error(0x0000, 'testTag', `Failed to get address. Code:${error.code}, message:${error.message}`);
              return;
            }
            this.ipResult = JSON.stringify(data);
            hilog.info(0x0000, 'testTag', `Succeeded to get data: ${JSON.stringify(data)}`);
          });
      });
    }
    ```
    
5.  获取中文域名地址对应的IP。由于未经过ASCII编码，因此预期结果为获取IP失败。
    
    ```
    this.getAddressName(false);
    ```
    
6.  将中文域名转换为对应ASCII编码后获取对应IP。
    
    ```
    this.getAddressName(true);
    ```
    
7.  将转换后的ASCII编码转成原中文域名。
    
    ```
    this.hostVal = connection.getDnsUnicode(this.hostVal);
    ```
    

#### DNS接口支持配置获取的IP地址类型

从API version 23开始，DNS解析支持通过options参数指定IP地址类型（如 IPv4 或 IPv6），也支持在特定的网络连接NetHandle上按给定的IP类型解析主机名，从而实现更精准的地址解析。

完整示例代码见：DNS\_case

1.  导入所需文件。
    
    ```
    import { connection } from '@kit.NetworkKit';
    import { hilog } from '@kit.PerformanceAnalysisKit';
    ```
    
2.  初始化数据成员。
    
    ```
    @State hostName: string = 'www.example.com';
    ```
    
3.  使用当前默认网络解析主机名以获取所有IP地址。
    
    ```
    connection.getAddressesByName(this.hostName).then((data: connection.NetAddress[]) => {
      hilog.info(0x0000, 'testTag', `Succeeded to get data: ${JSON.stringify(data)}`);
    })
    ```
    
4.  使用当前默认网络，指定IP类型解析主机名以获取指定IP地址。
    
    ```
    let options: connection.QueryOptions = {
      family: connection.FamilyType.FAMILY_TYPE_IPV4
    };
    connection.getAddressesByNameWithOptions(this.hostName, options).then((data: connection.NetAddress[]) => {
      hilog.info(0x0000, 'testTag', `Succeeded to get data: ${JSON.stringify(data)}`);
    });
    ```
    
5.  使用指定的网络连接（NetHandle），并按给定的IP类型解析主机名。
    
    ```
    let netSpecifier: connection.NetSpecifier = {
      netCapabilities: {
        // 假设当前默认网络是WiFi，需要创建蜂窝网络连接，可指定网络类型为蜂窝网。
        bearerTypes: [connection.NetBearType.BEARER_CELLULAR],
        // 指定网络能力为Internet。
        networkCap: [connection.NetCap.NET_CAPABILITY_INTERNET]
      },
    };
    
    // 指定超时时间为10s(默认值为0)。
    let timeout = 10 * 1000;
    
    // 创建NetConnection对象。
    let conn = connection.createNetConnection(netSpecifier, timeout);
    // 订阅事件，如果当前指定网络可用，通过on_netAvailable通知用户。
    conn.on('netAvailable', ((handle: connection.NetHandle) => {
      let options: connection.QueryOptions = {
        family: connection.FamilyType.FAMILY_TYPE_IPV4
      }
      // 当指定网络可用时，使用该网络连接解析主机名，并仅获取IPv4类型的地址
      handle.getAddressesByNameWithOptions(this.hostName, options).then((data: connection.NetAddress[]) => {
        hilog.info(0x0000, 'testTag', `Succeeded to get data: ${JSON.stringify(data)}`);
      })
    }));
    // 订阅事件，如果当前指定网络不可用，通过on_netUnavailable通知用户。
    conn.on('netUnavailable', ((data: void) => {
      hilog.info(0x0000, 'testTag', `net is unavailable, data is ${JSON.stringify(data)}`);
    }));
    ```