监听网络改变, 实时获取网络连通性,ping/发请求
Posted 想名真难
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了监听网络改变, 实时获取网络连通性,ping/发请求相关的知识,希望对你有一定的参考价值。
可以使用AFN框架中的AFNetworkReachabilityManager来监听网络状态的改变,也可以利用苹果提供的Reachability来监听。在开发中直接使用AFN框架处理更方便。
示例代码如下:
-(void)afn
//1.创建网络状态监测管理者
AFNetworkReachabilityManager *manger = [AFNetworkReachabilityManager sharedManager];
//2.监听改变
[manger setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status)
/*
AFNetworkReachabilityStatusUnknown = -1,
AFNetworkReachabilityStatusNotReachable = 0,
AFNetworkReachabilityStatusReachableViaWWAN = 1,
AFNetworkReachabilityStatusReachableViaWiFi = 2,
*/
switch (status)
case AFNetworkReachabilityStatusUnknown:
NSLog(@"未知");
break;
case AFNetworkReachabilityStatusNotReachable:
NSLog(@"没有网络");
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
NSLog(@"3G|4G");
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(@"WiFi");
break;
default:
break;
];
//3.开启监听
[manger startMonitoring];
Reachablity 是一个ios下检测设备网络环境用的库, 苹果对SCNetworkReachabilityRef的封装写的demo,我们可以直接使用, 下载源码后拖入工程即可。
苹果官方提供的Doc,下载地址:Documentation Archive, github地址
示例代码如下: 因为Reachablity只能监听网络状态的状况,不能监听它的改变,所以采用通知的方式-(void)viewDidLoad
[super viewDidLoad];
//注册通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityStatusChange) name:kReachabilityChangedNotification object:nil];
//创建对象
Reachability *reachability = [Reachability reachabilityForInternetConnection];
[reachability startNotifier];
self.reachability = r;
-(void)reachabilityStatusChange
if ([Reachability reachabilityForInternetConnection].currentReachabilityStatus == ReachableViaWWAN)
NSLog(@"3G|4G, %@",[self getNetType]);
return;
if ([Reachability reachabilityForLocalWiFi].currentReachabilityStatus == ReachableViaWiFi)
NSLog(@"wifi");
return;
NSLog(@"未知");
-(void)dealloc
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self.reachability stopNotifier];
2g/3g/4g/5g的判断可以参考getNetType方法
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
+ (NSString *)getNetType
CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init];
NSString *currentStatus = info.currentRadioAccessTechnology;
NSString *currentNet = @"";
if ([currentStatus isEqualToString:CTRadioAccessTechnologyGPRS])
currentNet = @"GPRS";
else if ([currentStatus isEqualToString:CTRadioAccessTechnologyEdge])
currentNet = @"2.75G EDGE";
else if ([currentStatus isEqualToString:CTRadioAccessTechnologyWCDMA])
currentNet = @"3G";
else if ([currentStatus isEqualToString:CTRadioAccessTechnologyHSDPA])
currentNet = @"3.5G HSDPA";
else if ([currentStatus isEqualToString:CTRadioAccessTechnologyHSUPA])
currentNet = @"3.5G HSUPA";
else if ([currentStatus isEqualToString:CTRadioAccessTechnologyCDMA1x])
currentNet = @"2G";
else if ([currentStatus isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0])
currentNet = @"3G";
else if ([currentStatus isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA])
currentNet = @"3G";
else if ([currentStatus isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB])
currentNet = @"3G";
else if ([currentStatus isEqualToString:CTRadioAccessTechnologyeHRPD])
currentNet = @"HRPD";
else if ([currentStatus isEqualToString:CTRadioAccessTechnologyLTE])
currentNet = @"4G";
else if (@available(iOS 14.0, *))
if ([currentStatus isEqualToString:CTRadioAccessTechnologyNRNSA])
currentNet = @"5G NSA";
else if ([currentStatus isEqualToString:CTRadioAccessTechnologyNR])
currentNet = @"5G";
return currentNet;
+ (NSString *)networkStatus
Reachability *reachability = [Reachability reachabilityWithHostName:@"www.apple.com"];
NetworkStatus internetStatus = [reachability currentReachabilityStatus];
NSString *net = @"WIFI";
switch (internetStatus)
case ReachableViaWiFi:
net = @"WIFI";
break;
case ReachableViaWWAN:
net = [self getNetType]; //判断具体类型
break;
case NotReachable:
net = @"当前无网路连接";
default:
break;
return net;
AF和 Reachablity都是对SCNetworkReachabilityRef的封装, 实际工程中使用AF还是更方便的.
上面的2种方式在底层原理上都是通过SCNetworkReachability来实现网络检测的, 官方的注释也写的很清楚, 只是告诉你当前使用的是什么网络, 但是不能保证能连接到xx服务器. 也无法检测实际网络连接情况。
"Reachability cannot tell your application if you can connect to a particular host, only that an interface is available that might allow a connection, and whether that interface is the WWAN."
可访问性无法告诉您的应用程序是否可以连接到特定主机,只能告诉您有可能允许连接的接口,以及该接口是否是WWAN。无法检测实际的网路情况
想要检测真正的网络状态, 目前想到的比较合理的方案有2个.
- 通过发起一个真正的请求, 这个请求尽可能的轻巧, 尽可能的快,目前找的是一个淘宝的获取时间戳的接口. 这个接口最好是作为app的启动配置项, 如果地址失效了, 服务器在配一个其他的, 或者服务器自己提供类似的接口也可以.
http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp - 通过ping 服务器地址来实现, 但是ping有一个问题, ping是基于ip协议的icmp协议, 可能会出现服务器是可以ping通的, 但是正常的接口是失败的.
正常网络 | 无网 | 设置代理,代理关闭 | 设置代理,代理开启 | 手机开热点,有网 | 手机开热点,无网 | |
---|---|---|---|---|---|---|
ping | 通过 | 不通过 | 通过 | 通过 | 通过 | 不通过 |
接口 | 通过 | 不通过 | 不通过 | 通过 | 通过 | 不通过 |
正常接口 | 通过 | 不通过 | 不通过 | 通过 | 通过 | 不通过 |
ping是ICMP协议中常用网络管理命令.
ICMP(Internet Control Message Protocol)Internet控制报文协议。它是TCP/IP协议簇的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。
ICMP使用IP的基本支持,但是,ICMP实际上是IP的一个组成部分,必须由每个IP模块实现。手机设置代理是配置HTTP协议的, 无法把ICMP协议也指定.
所以上面出现了设置代理, 代理关闭的情况下, ping能通, 而接口不能通过.
ping方案, 使用苹果提供的demo的SimplePing, 然后封装了一下, 调用如下
ULPingHelper *pingHelper = [[ULPingHelper alloc] init];
pingHelper.host = @"www.baidu.com";
[pingHelper pingWithBlock:^(BOOL isSuccess, NSString * _Nonnull ipString, NSTimeInterval latency)
if (isSuccess)
NSLog(@"成功 %@ %@ %d ms",pingHelper.host,ipString,(int)latency);
else
NSLog(@"失败 %@ %@ %d ms",pingHelper.host,ipString,(int)latency);
];
发请求方案, 使用了NSURLSession, 注意发起的Request一定要设置缓存策略为NSURLRequestReloadIgnoringCacheData, 有可能get请求会被系统缓存, 出现网络其实不通, 但是本地有数据, 缓存返回了本地数据, 出现错误的判断.
+ (void)requestAction
// 与接口表现一致
// 接口有失效风险,能换成自己的服务器最好
NSLog(@"-- 开始");
NSURL *url = [NSURL URLWithString:@"http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp"];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:2];
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error)
if (error)
NSLog(@"-- 出错");
else
NSLog(@"-- 正常");
] resume];
2种方案的demo地址: https://github.com/guochaoshun/NetWorking
参考文章:
ping方案中中读取ping的服务器ip地址, GitHub - lovesunstar/STPingTest
以上是关于监听网络改变, 实时获取网络连通性,ping/发请求的主要内容,如果未能解决你的问题,请参考以下文章