本文檔介紹了Unity情境下的接入移動解析HTTPDNS的方案。
一、概述
Unity是內容創作引擎。Unity可以開發:2D/3D遊戲,2D/3D應用,VR,AR,甚至移動App,網頁前端 ,電影即時渲染等,創作者可以藉助Unity將創意變成現實。
為方便 Unity 開發人員接入使用移動解析HTTPDNS SDK,我們提供了針對Unity情境下的PdnsUnityDemo源碼供使用者參考,源碼中提供了移動解析HTTPDNS Unity外掛程式。
PdnsUnityDemo使用的是Unity 2019.4.21f1c1開發版本,Assets/Plugins目錄下為外掛程式(使用者也可根據實際情況使用阿里雲DNS SDK來製作外掛程式),外掛程式使用了定製的Gradle檔案和Proguard檔案,如果您的專案有其他地方也定製了這些檔案,將內容合并即可。
二、整合方式
匯入Plugins檔案。
將PdnsUnityDemo中 Plugins 檔案夾中的檔案複製到您 Unity 工程>Assets>Plugins 檔案夾中。
配置參數。
AlipdnsHelper.setAccountIdAndSetAccessKeyIdAndSetAccesskeySecret("accountId","accessKeyId","accesskeySecret");
AlipdnsHelper.setCacheEnable(true);
AlipdnsHelper.setSchedulePrefetchEnable(true);
AlipdnsHelper.setIspEnable(true);
AlipdnsHelper.setMaxCacheTTL(3600);
AlipdnsHelper.setMaxNegativeCache(60);
AlipdnsHelper.setScheme(1);
AlipdnsHelper.setShortEnable(false);
AlipdnsHelper.setSpeedTestEnable(true);
AlipdnsHelper.setCacheCountLimit(100);
AlipdnsHelper.setSpeedPort(80);
// 預解析網域名稱
List<string> list = new List<string>();
list.Add("網域名稱1");
list.Add("網域名稱2");
AlipdnsHelper.setPreloadDomains(list);三、API介紹
介面類為AlipdnsHelper.cs。
必傳參數,accountId,您在控制台註冊後,控制台會產生唯一標識Account ID。
必傳參數,accessKeyId,accessKeySecret 在控制台開啟鑒權後產生該參數,設定鑒權功能來保障使用者身份安全,不被第三方未授權者盜用。
public static void setAccountIdAndSetAccessKeyIdAndSetAccesskeySecret(string accountId,string accessKeyId,string accessKeySecret)設定開啟緩衝,在第一次解析過網域名稱後,後續再解析時, 優先擷取緩衝中的資料,可大大提高解析速度。
public static void setCacheEnable(bool enable)設定是否開啟定時主動更新到期緩衝,開啟後SDK每分鐘會自動更新到期緩衝,保障使用者快取資料及時更新,但是可能會帶來網域名稱解析次數和用戶端流量消耗的增多。
public static void setSchedulePrefetchEnable(bool enable)設定是否開啟依據ISP網路區分網域名稱緩衝,開啟後則在不同網路環境下網域名稱快取資料分別儲存互不影響。如果不開啟,則在不同網路下使用同一份網域名稱快取資料。
public static void setIspEnable(bool enable)設定緩衝最大TTL時間,如果設定了該時間,則會限制緩衝的最大TTL不超過該設定時間。
SDK預設該參數為3600s。
public static void setMaxCacheTTL(double maxCacheTTL)設定否定緩衝最大TTL時間,設定了該時間,則會限制否定緩衝的最大TTL不超過該設定時間。
SDK預設該參數為30s。
public static void setMaxNegativeCache(double maxNegativeCache)在訪問DNS伺服器進行解析時,是通過HTTP協議解析,還是通過HTTPS協議解析,可通過
scheme屬性進行設定。scheme預設是0,使用HTTP協議進行解析,建議使用HTTP協議進行解析,解析速度更快,scheme設為1即使用HTTPS協議進行解析。
public static void setScheme(int scheme)設定是否開啟short模式,移動解析HTTPDNS的DoH JSON API返回資料分為全量JSON和簡要IP數組格式。SDK預設為全量JSON格式。
public static void setShortEnable(bool enable)設定是否開啟IP優選,開啟後解析結果數組會按照測速結果由快到慢的順序排列。
public static void setSpeedTestEnable(bool enable)設定緩衝數量,可以自訂緩衝數量(支援範圍100~500之間)。
public static void setCacheCountLimit(int cacheCountLimit)設定IP測速優選連接埠,設定socket探測指定連接埠。
public static void setSpeedPort(int speedPort)由於SDK內建緩衝功能,在第一次解析完網域名稱後,後續再次解析此網域名稱可大大提高解析速度,所以建議在app啟動後,可對app中可能要解析的網域名稱進行預先載入。
public static void setPreloadDomains(List<string> hosts)自動感知網路環境(ipv4-only、ipv6-only、ipv4和ipv6雙棧)直接從緩衝中擷取適用於當前網路環境的IP數組,無需等待。如無緩衝,或有緩衝但已到期並且expiredIPEnabled為false,則返回空。
@param host 網域名稱
@param expiredIPEnabled 是否允許返回到期ip
public static List<string> getIpsByCacheWithDomain(string host, bool expiredIPEnabled)直接從緩衝中擷取ipv4解析結果,無需等待. 如無緩衝,或有緩衝但已到期,並且expiredIPEnabled為false,則返回空。
@param host 網域名稱
@param expiredIPEnabled 是否允許返回到期ip
public static List<string> getIpv4ByCacheWithDomain(string host, bool expiredIPEnabled)直接從緩衝中擷取ipv6解析結果,無需等待. 如無緩衝,或有緩衝但已到期,並且expiredIPEnabled為false,則返回空。
@param host 網域名稱
@param expiredIPEnabled 是否允許返回到期ip
public static List<string> getIpv6ByCacheWithDomain(string host, bool expiredIPEnabled)擷取請求移動解析HTTPDNS成功失敗統計資訊。
public static string getRequestReportInfo()四、最佳實務
4.1 原理說明
本樣本展示了Unity中整合HTTPDNS的完整解決方案:
跨平台統一介面:使用
AlipdnsHelper提供統一的API介面平台特定實現:針對 iOS、Android、 SDK提供不同的底層實現
自動DNS替換:在網路請求前自動將網域名稱替換為解析的IP地址
Host頭設定:確保HTTPS/SSL串連的SNI正確性
4.2 網路請求整合
當使用不同的網路模組發送請求時,需要相應地進行要求標頭配置等操作,下面對HttpClient、HttpWebRequest、UnityWebRequest三種類型分別給出樣本:
4.2.1 HttpClient
using System;
using System.Net.Http;
using UnityEngine;
public class AlipdnsHttpClient : MonoBehaviour
{
private static readonly HttpClient httpClient = new HttpClient();
public async void MakeRequest(string url)
{
try
{
var uri = new Uri(url);
string hostname = uri.Host;
// 使用HTTPDNS解析網域名稱
var result = AlipdnsHelper.getIpsByCacheWithDomain(host, true);
if (result != null && result.Count > 0)
{
string resolvedIP = result[0];
string newUrl = url.Replace(hostname, resolvedIP);
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, newUrl))
{
// 關鍵:設定Host頭保證SSL/SNI正確性
requestMessage.Headers.Host = hostname;
var response = await httpClient.SendAsync(requestMessage);
string content = await response.Content.ReadAsStringAsync();
Debug.Log($"請求成功: {response.StatusCode}");
}
}
}
catch (Exception e)
{
Debug.LogError($"請求失敗: {e.Message}");
}
}
}4.2.2 HttpWebRequest
using System;
using System.IO;
using System.Net;
using UnityEngine;
public class AlipdnsWebRequest : MonoBehaviour
{
public void MakeRequest(string url)
{
try
{
var uri = new Uri(url);
string hostname = uri.Host;
// 使用HTTPDNS解析網域名稱
var result = AlipdnsHelper.getIpsByCacheWithDomain(host, true);
if (result != null && result.Count > 0)
{
string resolvedIP = result[0];
string newUrl = url.Replace(hostname, resolvedIP);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(newUrl);
request.Method = "GET";
// 關鍵:設定Host頭保證SSL/SNI正確性
request.Host = hostname;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
string content = reader.ReadToEnd();
Debug.Log($"請求成功: {response.StatusCode}");
}
}
}
catch (Exception e)
{
Debug.LogError($"請求失敗: {e.Message}");
}
}
}4.2.3 UnityWebRequest(不推薦)
由於UnityWebRequest無法正確配置SNI(伺服器網域名稱指示)資訊,當伺服器依賴SNI返回特定網域名稱認證時,會導致SSL驗證失敗。因此處理這類網域名稱時,推薦使用前兩種網路請求方式。
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
public class AlipdnsUnityWebRequest : MonoBehaviour
{
public IEnumerator MakeRequest(string url)
{
var uri = new Uri(url);
string hostname = uri.Host;
// 使用HTTPDNS解析網域名稱
var result = AlipdnsHelper.getIpsByCacheWithDomain(host, true);
if (result != null && result.Count > 0)
{
string resolvedIP = result[0];
string newUrl = url.Replace(hostname, resolvedIP);
using (UnityWebRequest request = UnityWebRequest.Get(newUrl))
{
// 關鍵:設定Host頭
request.SetRequestHeader("Host", hostname);
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
Debug.Log($"請求成功: {request.responseCode}");
}
else
{
Debug.LogError($"請求失敗: {request.error}");
}
}
}
}
}當前文檔只針對Unity情境下移動解析HTTPDNS Android/iOS SDK的使用。
關於移動解析HTTPDNS Android/iOS SDK的接入與使用問題,請查看Android SDK開發指南、iOS SDK開發指南。
開發人員在Unity情境下接入移動解析HTTPDNS Android/iOS SDK實踐完整代碼請參考PdnsUnityDemo源碼。