前言
??手機網(wǎng)絡(luò)連接狀態(tài)的檢測對于iOS
開發(fā)來說是一個非彻饧冢基礎(chǔ)的需求坤次。為了更好的用戶體驗步鉴,我們會在無網(wǎng)絡(luò)時展現(xiàn)本地或者緩存的內(nèi)容揪胃,并對用戶進行合適的提示。對于網(wǎng)絡(luò)狀態(tài)的檢測氛琢,蘋果提供了Reachability喊递,由此也衍生出各種 Reachability
框架,比較著名的有Github
上的 tonymillion/Reachability 以及 AFNetworking
中的 AFNetworkReachabilityManager
模塊阳似,它們的實現(xiàn)原理基本上是完全相同的骚勘。
??但事實上,此方案能獲取的只是設(shè)備的本地連接狀態(tài)撮奏,有時它很難為我們檢測真正的網(wǎng)絡(luò)連接狀態(tài)俏讹,如以下場景:
- 現(xiàn)在很多的公共場所的
WiFi
,需要網(wǎng)頁登錄授權(quán)畜吊,授權(quán)之前無法上網(wǎng)泽疆,但本地連接已經(jīng)建立; - 存在了本地網(wǎng)絡(luò)連接玲献,但信號很差殉疼,實際無法連接到服務(wù)器;
-
iOS
連接的路由設(shè)備本身沒有連接外網(wǎng)等捌年。
Ping
??ping 是 Windows
瓢娜、Unix
、Linux
和macOS
等系統(tǒng)下一個常用的命令礼预,利用 ping
命令可以用來測試數(shù)據(jù)包 (ICMP) 能否通過IP
協(xié)議到達特定主機眠砾,并收到主機的應(yīng)答,以檢查網(wǎng)絡(luò)是否連通和網(wǎng)絡(luò)連接速度托酸,幫助我們分析和判定網(wǎng)絡(luò)故障荠藤。
??SimplePing是蘋果封裝好的ping
的功能,它利用resolve host
获高,create socket
(send
&recv data
)哈肖,解析ICMP
包驗證 checksum
等實現(xiàn)了 ping
功能。并且支持iPv4
和 iPv6
念秧。
SimplePing類結(jié)構(gòu)
SimplePing
的使用很簡單:
// 1. 利用 HostName 創(chuàng)建 SimplePing
self.simplePing = [[SimplePing alloc] initWithHostName:@"www.apple.com"];
// 2. 指定 IP 地址類型淤井,默認是都支持
if (isIpv4 && !isIpv6) {
self.simplePing.addressStyle = SimplePingAddressStyleICMPv4;
}else if (isIpv6 && !isIpv4) {
self.simplePing.addressStyle = SimplePingAddressStyleICMPv6;
}
// 3. 設(shè)置 delegate,用于接收回調(diào)信息
self.simplePing.delegate = self;
// 4. 開始 ping
[self.simplePing start];
然后在delegate
中進行回調(diào),代理方法中提現(xiàn)了ping
的過程:
// [self.simplePing start] 成功之后,解析 HostName 拿到 ip 地址之后币狠,發(fā)送封包
- (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address
{
//這里面可以創(chuàng)建一個時間戳NSTimer定時發(fā)送數(shù)據(jù)監(jiān)測
[self.simplePing sendPingWithData:nil];
}
// [self.simplePing start] ping 功能啟動失敗
- (void)simplePing:(SimplePing *)pinger didFailWithError:(NSError *)error
{
//停止所以的請求游两,如果有時間戳也停止
[self.simplePing stop];
}
// sendPingWithData 發(fā)送數(shù)據(jù)成功
- (void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber
{
NSLog(@"#%u sent", sequenceNumber);
}
// sendPingWithData 發(fā)送數(shù)據(jù)失敗,并返回錯誤信息
- (void)simplePing:(SimplePing *)pinger didFailToSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber error:(NSError *)error
{
NSLog(@"#%u send failed: %@", sequenceNumber,error);
}
// ping 發(fā)送封包之后收到響應(yīng)
- (void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber
{
NSLog(@"#%u received, size=%zu", sequenceNumber, packet.length);
}
// ping 接收響應(yīng)封包發(fā)生異常
- (void)simplePing:(SimplePing *)pinger didReceiveUnexpectedPacket:(NSData *)packet
{
NSLog(@"unexpected packet, size=%zu", packet.length);
}
??梳理了一下使用SimplePing
類進行 ping
操作的流程如下圖所示:
注意在SimplePing
對象實例化一定要使用一直持有對象的屬性方法漩绵。
??因此贱案,在Reachability的方法優(yōu)化后采用了ping
更加精確的獲取網(wǎng)絡(luò)的連接狀態(tài),網(wǎng)上有的不錯的第三方庫比如RealReachability就是采用了這種方法止吐。
Demo下載
參考文檔
https://blog.csdn.net/mnbvcxz111123/article/details/54286050
Traceroute(路由追蹤)的原理及實現(xiàn)
iOS--網(wǎng)絡(luò)測試小工具(ping tarceroute)
網(wǎng)易網(wǎng)絡(luò)診斷