Android NDK 層發起 HTTP 請求的問題及解決

swmz9632 7年前發布 | 12K 次閱讀 HTTP 安卓開發 Android開發 移動開發

前言

新的一年,大家新年快樂~~雞年大吉!

本次給大家帶來何老師的最新文章~雖然何老師還在過節,但依然放心不下廣大開發者,在此佳節還未結束之際,給大家帶來最新的技術分享~

NDK層網絡請求

事件的起因不說了,總之是需要實現一個 NDK 層的網絡請求。為了多端適用,還是選擇了 CodeTyphon 作為跨平臺方案。關于 CodeTyphon 此處不述,感興趣的可以直接去其官網查看(傳送門:http://www.pilotlogic.com/sitejoom/)。

CodeTyphon 自帶的 fcl-web 庫可以直接完成對于 HTTP 請求的支持,雖然我很想這么說... 在實際使用中,的確可以通過引入  fcl-web 來完成跨平臺的網絡請求,然而在 Android 端實際測試時,卻發生了奇怪的錯誤。

比如說請求我自己的服務器 www.rarnu.com ,會發生以下錯誤:

而當我換用 IP 地址來請求時,卻是可以成功的。

輸入的域名是實際存在的,可以排除掉域名本身的問題。而使用 adb shell 連入設備,并使用  ping 命令訪問該域名,也是正常的。

那么問題可能就出在,找不到 nameserver 。我們都知道,在 Linux 下, nameserver 由  resolv.conf 決定,這個文件通常保存在  /etc 下。于是看了一下,Android 里并沒有這個文件,應該就是這個原因引起的了,因為讀不到  resolv.conf 所以才導致了無法解釋域名。接下來就是去找 Android 下,原本該是  resolv.conf 的東西保存在哪里。

不賣關子了,其實 Android 很早就把 resolv.conf 的內容改成了 key-value 的形式,采用 SystemProperties 進行存儲,而其關鍵的 key 是  net.dns1 和  net.dns2 。

嘗試使用 adb 連接手機,并對以上兩個 key 進行取值:

我的手機上取出來的是 OpenDNS 的值,自己設置過。好了,既然已經知道了 nameserver 的所在,接下去就是修改代碼以使程序識別和加載。

在 CodeTyphon 中,有一個基礎庫文件叫 netdb.pp ,其中包含了  resolveName 方法,其具體代碼如下:

其實這段代碼很明確,關鍵變量是 DNSServers ,打印一下看看是個什么值:

程序執行后打出來 -1 ,也就是說在 Android 下,由于  DNSServers 變量中沒有任何的數據,導致了完全無法解析域名,在其他平臺下,在此處打日志均顯示  0 ,表示在這個數組里有一個下標為 0 的數據。

那事情就變得簡單了,我們可以直接去找加載了 DNSServers 的地方,很容易的,找到了  InitResolver 函數,由于該函數比較長,此處只截取加載  DNSServer 的部分:

Android NDK 層發起 HTTP 請求的問題及解決

沒有比這更明確的了,就是去找有沒有 /etc/resolv.conf 嘛,找到就加載,沒找到那就啥都不做了,而剛才說過了 Android 端并沒有這么一個文件,于是直接就導致了  nameserver 缺失,間接引起域名無法解析。

好了,那么簡易的解決方案也就有了,只需要重建 GetDNsservers 函數,使其能夠適應 Android 端的情況即可。

下面給出代碼:

Android NDK 層發起 HTTP 請求的問題及解決

里面還有一個關鍵代碼,是 GetNetDNS ,它用于從 Android 內讀取  net.dns1 變量:

Android NDK 層發起 HTTP 請求的問題及解決

最后,把上面的 InitResolver 改一下,使其可以正常加載工作于 Android 端的這段代碼:

Android NDK 層發起 HTTP 請求的問題及解決

編譯運行程序, Error resolving host 的問題即得到了解決。

 

來自:http://mp.weixin.qq.com/s/O2APsNzYqjPGAp9sDo-MyA

 

 本文由用戶 swmz9632 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!