iOS 10 在進(jìn)行 Socket 通訊產(chǎn)生的坑...

關(guān)鍵詞

CocoaAsyncSocket Socket iOS 10 網(wǎng)絡(luò)權(quán)限彈框

癥狀

昨天,為了可以讓硬件的同事測(cè)試 UDP Socket 收發(fā)包,所以去寫了一個(gè)集成了 CocoaAsyncSocket 可以完成基本持續(xù)發(fā)包的 Demo 。但是拿同事的手機(jī),一直都沒(méi)有看到建立連接-發(fā)包成功等等的回調(diào)。
然后測(cè)試了其他多款不同型號(hào),不同機(jī)型的手機(jī),都沒(méi)有出現(xiàn)這個(gè)問(wèn)題。

定位問(wèn)題

  1. 代理失效?
    因?yàn)閺某绦蜻\(yùn)行的結(jié)果直觀的來(lái)看,只是沒(méi)有回調(diào)返回。所以直接入回調(diào)方法入手,到 GCDAsyncUdpSocket.m 的源碼中打斷點(diǎn),結(jié)果一路單步過(guò)來(lái),發(fā)現(xiàn)delegate始終都是有的,而且涉及到 Delegate 的方法一直都沒(méi)有被調(diào)用。
  2. 網(wǎng)絡(luò)錯(cuò)誤?
    在之前在對(duì) GCDAsyncUdpSocket.m 的源碼的探究中,了解到它的源碼是由下面幾部分構(gòu)成
Configuration / Delegate Helpers / Errors / Utilities
Diagnostics / Binding / Connecting / Multicast
Reuse port / Broadcast / Sending / Receiving
Closing / CFStream / Advanced / Class Methods

所以直接從Error部分入手,在每個(gè)方法的開(kāi)始打斷點(diǎn),當(dāng)進(jìn)行發(fā)包的時(shí)候,發(fā)現(xiàn)程序停在了- errnoErrorWithReason:這個(gè)方法里。這個(gè)方法中通過(guò) NSString *errMsg = [NSString stringWithUTF8String:strerror(errno)]這段代碼來(lái)獲取錯(cuò)誤信息,errno 這是什么呢?

  • errno

errno 是記錄系統(tǒng)的最后一次錯(cuò)誤代碼。代碼是一個(gè)int型的值,在errno.h中定義。我們可以通過(guò)檢查errno這個(gè)值,來(lái)獲悉系統(tǒng)發(fā)生錯(cuò)誤的原因。在這個(gè)庫(kù)中,errno值可以讓我們定位到 socket 通信中產(chǎn)生的錯(cuò)誤。

errno.h這個(gè)文件中,宏定義了一部分系統(tǒng)中各種產(chǎn)生的錯(cuò)誤,并對(duì)應(yīng)著errno的值。

然后查找到errno的值是65,對(duì)應(yīng)的錯(cuò)誤是no route to host 就是無(wú)法進(jìn)行網(wǎng)絡(luò)訪問(wèn)。

問(wèn)題原因

因?yàn)槎ㄎ坏搅藛?wèn)題在于沒(méi)有網(wǎng)絡(luò)訪問(wèn),所以通過(guò) iOS 10 無(wú)法訪問(wèn)網(wǎng)絡(luò)等關(guān)鍵詞查到了 大神倉(cāng)的文章 iOS 10 的坑:新機(jī)首次安裝 app,請(qǐng)求網(wǎng)絡(luò)權(quán)限“是否允許使用數(shù)據(jù)” 以及其中提到的稀土的一篇講 關(guān)于 iOS 10 應(yīng)用程序網(wǎng)絡(luò)請(qǐng)求許可彈窗解決方法的文章。
其中說(shuō)到了由于大陸相關(guān)部門出臺(tái)的新規(guī)定指出,應(yīng)用在未經(jīng)用戶允許的前提下,系統(tǒng)不能授予其使用聯(lián)網(wǎng)、獲取定位的功能,所以只有在用戶點(diǎn)擊了彈窗允許訪問(wèn)網(wǎng)絡(luò)的時(shí)候,應(yīng)用程序才能訪問(wèn)網(wǎng)絡(luò)。
然后發(fā)現(xiàn),我拿的這個(gè)手機(jī)的蜂窩移動(dòng)數(shù)據(jù)界面,果然是需要設(shè)置應(yīng)用程序允許訪問(wèn)網(wǎng)絡(luò)的那款。

左圖是不會(huì)彈框的機(jī)型,右圖則是會(huì)的

系統(tǒng)的BUG

引用掘金的一句話說(shuō)明一下我遇到的情況...
如果你在 iOS 10 操作系統(tǒng)中安裝了一個(gè)新應(yīng)用或者第一次打開(kāi)某個(gè)應(yīng)用時(shí)發(fā)現(xiàn)應(yīng)用出現(xiàn)無(wú)法訪問(wèn)網(wǎng)絡(luò)無(wú)法刷新數(shù)據(jù)的情況,并且在蜂窩數(shù)據(jù)網(wǎng)絡(luò)的設(shè)置項(xiàng)中無(wú)法找到相應(yīng)應(yīng)用的聯(lián)網(wǎng)權(quán)限設(shè)置選項(xiàng)

看了掘金的文章,他們定位的原因是:iOS 10 系統(tǒng)沒(méi)有正確地配置網(wǎng)絡(luò)權(quán)限,所以觸發(fā)一下系統(tǒng)的相關(guān)設(shè)置改動(dòng)可能能夠重新激活應(yīng)用的聯(lián)網(wǎng)權(quán)限請(qǐng)求彈窗

然后又咨詢了一下公司的大神,公司的大神表示看到了很多,基本上直接使用socket通訊是一般是不會(huì)觸發(fā)聯(lián)網(wǎng)權(quán)限的。然后查到了** EsptouchForIOS** 程序的issue,里面有這樣的解答。
經(jīng)過(guò)研究發(fā)現(xiàn),ios9直接升級(jí)到ios10.0.1的所有應(yīng)用默認(rèn)關(guān)閉所有網(wǎng)絡(luò)權(quán)限,ios9直接升級(jí)到ios10.0.2的所有應(yīng)用默認(rèn)打開(kāi)所有網(wǎng)絡(luò)權(quán)限。但是,我們的Esptouch使用的都是底層的Socket函數(shù),未使用Cocoa Touch框架。所以,未向用戶申請(qǐng)Network權(quán)限。
然后 Demo 使用的UDPAsyncSocket.h中,使用也是底層的Socket函數(shù)。。。

解決方案

于是在 Demo 進(jìn)行 socket 發(fā)包前

  • 進(jìn)行了一次URLSession的請(qǐng)求來(lái)觸發(fā)網(wǎng)絡(luò)權(quán)限的彈窗
  • 并重置了一下手機(jī)的網(wǎng)絡(luò)設(shè)置。
  • Run
    Bingo!!!之后就成功的看到了權(quán)限彈窗,點(diǎn)擊之后,可以成功發(fā)包了

參考鏈接

下面是一些產(chǎn)品碰到這個(gè)問(wèn)題的解決方案,畢竟我這只是一個(gè)用于調(diào)試 UDP Socket 發(fā)包的 Demo。
EsptouchForIOS關(guān)于這個(gè)問(wèn)題的解答
iOS 10 不提示「是否允許應(yīng)用訪問(wèn)數(shù)據(jù)」,導(dǎo)致應(yīng)用無(wú)法使用的解決方案
iOS 10 的坑:新機(jī)首次安裝 app,請(qǐng)求網(wǎng)絡(luò)權(quán)限“是否允許使用數(shù)據(jù)”
ios10網(wǎng)絡(luò)權(quán)限問(wèn)題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容