我测试了不同的框架,例如
我想知道主机是否可以访问。在我的iPhone上,我将iMac设置为代理(Charles)并阻止或不阻止连接,但可达性始终为YES。仅当我设置不存在的主机时,它才返回NO。但是如果主机存在但我阻止了与它的连接,我总是得到isReachable
。是不是有办法检查主机真的是否可以访问?
如果我尝试使用KSReachability,我会执行以下操作:
self.reachability = [KSReachability reachabilityToHost:@"www.stackoverflow.com"];
self.reachability.notificationName = kDefaultNetworkReachabilityChangedNotification;
self.reachability.onReachabilityChanged = ^(KSReachability *reachability) {
NSLog(@"isReachable: %i", reachability.reachable);
};
我总是通过以下配置获得isReachable: 1
:
当我尝试在Safari中访问www.stackoverflow.com时,页面无法打开(正如预期的那样)。在这种情况下,我希望可达性为假(isReachable: 0
)。
修改 所以对我来说最重要的问题是 - 如何实现我期待的行为?即应用程序会不断检查给定主机是否真的可以访问?
答案 0 :(得分:7)
代码声明:
self.reachability = [KSReachability reachabilityToHost:@"www.stackoverflow.com"];
实际上调用以下方法:
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL,
[hostName UTF8String]);
SCNetworkReachability参考说:
SCNetworkReachability编程接口允许应用程序 确定系统当前网络配置的状态 以及目标主机的可达性。考虑远程主机 当数据包由应用程序发送到网络时可达 堆栈,可以离开本地设备。可达性不保证 实际上主机将接收数据包。
说明清除iOS系统不向外界发送任何请求以检查可达性。它只是告诉数据包可以离开设备。如果系统要发送请求,它会自动表示它已连接到网络。
您可以通过提及“www.stackoverflow.com”这样的有效主机来验证这一点,并查看未发送请求的查尔斯(首先取消阻止)。您还可以查看其他有效的主机名,例如“www.abcdefgh。 com“(通过在Safari中运行并查看查尔斯来验证这一点)它还为您提供了可访问性,但查尔斯没有显示请求。如果您在任何有效主机之前放置http://,例如”http://www.stackoverflow.com“它也将无法达到可达性。所以很明显它不是传出的http请求。如果系统必须在外面发送请求,那么提供课程的重点是什么?开发人员可以创建网络连接并尝试连接到主机,看看它是通过还是失败。
然而有趣的是,如果提供像“www.hjjkhkhk.com”这样的无效主机,iOS系统会将可达性视为错误。现在的问题是iOS系统如何在不向外界发送任何查询的情况下找到有效或无效的主机?可能是它定期缓存DNS范围列表???对我来说非常不可能。
答案 1 :(得分:4)
在AppDelegate
添加此方法:
#import "Reachability.h"
-(NSString *)checkNetworkConnectivity
{
NSString *networkValue;
Reachability *rc = [Reachability reachabilityWithHostName:@"www.stackoverflow.com"];
NetworkStatus internetStatus = [rc currentReachabilityStatus];
if(internetStatus==0)
{
networkValue = @"NoAccess";
}
else if(internetStatus==1)
{
networkValue = @"ReachableViaWiFi";
} else if(internetStatus==2)
{
networkValue = @"ReachableViaWWAN";
}
else
{
networkValue = @"Reachable";
}
return networkValue;
}
检查主机是否可以访问
NSString *netStr = [appDelegate checkNetworkConnectivity];
if([netStr isEqualToString:@"NoAccess"])
{
[appDelegate callNoNetworkAlert];
}
答案 2 :(得分:3)
首先,除非我们看到一些代码,否则我们无法确定您正在做什么,您正在以正确的方式行事。但是我会假设你正确地做到了。
其次,您应该测试FreeNickname在评论中建议的内容。可能它实际上并不可达,并且当您期望有不同的响应时,可达性正确起作用。
最后,但非常重要,来自Reachability docs:
注意:如果您可以连接到特定主机,只有可用于允许连接的接口以及该接口是否为WWAN,则可访问性无法告诉您的应用程序。
这意味着,即使您的服务器可能没有返回任何响应,Reachability也不会检查。它仅检查您的服务器是否可用,以便可以发送数据包。它对该数据包的作用与Reachability无关。如果Reachability能够传输整个数据包,则假定您的主机可以访问。它将返回无法访问 iff 您的服务器已关闭,断开连接或不存在。
答案 3 :(得分:2)
我想补充一点,要在运行时收听网络更改,您需要收听告知您网络状态已更改的通知。
您可以这样做:
AppDelegate
文件中实现一个侦听器。[[NSNotificationCenter defaultCenter] addObserver:self 选择:@选择(reachabilityChanged :) name:kReachabilityChangedNotification object:nil];
reachabilityChanged
。您可以在reachabilityChanged
活动像:
- (void) reachabilityChanged:(NSNotification *)note
{
Reachability* reachability = [note object];
if (reachability == self.hostReachability)
{
isHostReachable = YES; //A flag to keep track of connectivity
}
if (reachability == self.internetReachability)
{
isInternetAvailable = YES;
}
if (reachability == self.wifiReachability)
{
isWifiAvailable = YES;
}
//If all are true that means we have host and Internet available
if (isHostReachable && isInternetAvailable && isWifiAvailable)
{
isInternetAvailable = true;
}
}
希望这会对你有所帮助。
答案 4 :(得分:1)
令人愉快的iOS和OS X网络框架 http://afnetworking.com
AFNetworkReachabilityManager
监控域的可达性,以及WWAN和WiFi网络接口的地址。
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status)
{
NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));
}];
NSURL *baseURL = [NSURL URLWithString:@"http://example.com/"];
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:baseURL];
NSOperationQueue *operationQueue = manager.operationQueue;
[manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status)
{
switch (status)
{
case AFNetworkReachabilityStatusReachableViaWWAN:
case AFNetworkReachabilityStatusReachableViaWiFi:
[operationQueue setSuspended:NO];
break;
case AFNetworkReachabilityStatusNotReachable:
default:
[operationQueue setSuspended:YES];
break;
}
}];