问题
I need to detect whether iphone is connected to VPN or not, programatically. I am developing a app which try to load URL, this page open only when device is connected to VPN. Before loading this URL I need to check VPN connectivity. I tried the following . But this is not working as expected.
- (BOOL)checkForVPNConnectivity {
NSDictionary *dict = (__bridge NSDictionary *)(CFNetworkCopySystemProxySettings());
//NSLog(@"cfnetwork proxy setting : %@", dict);
return [dict count] > 0;
}
回答1:
I do not believe that one should determine VPN connectivity by checking for a non-zero number of elements in the CFNetworkCopySystemProxySettings()
. (For example, I see entries when on a WiFi network, but not on a VPN.)
So, two observations:
I would consider using the
SystemConfiguration.framework
and use the following code with the hostname of something on your VPN:- (BOOL)checkForConnectivity:(NSString *)hostName { BOOL success = false; SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]); SCNetworkReachabilityFlags flags; success = SCNetworkReachabilityGetFlags(reachability, &flags); CFRelease(reachability); NSLog(@"success=%x", flags); // this is the standard non-VPN logic, you might have to alter it for VPN connectivity BOOL isAvailable = success && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired); if (isAvailable) { NSLog(@"Host is reachable: %d", flags); return YES; }else{ NSLog(@"Host is unreachable"); return NO; } }
Assuming that
success
is non-zero, you might have to do some empirical research on the setting of the bits inflags
. See SCNetworkReachability Reference for the technical definitions of these flags. I've heard claims that they getkSCNetworkReachabilityFlagsReachable | kSCNetworkReachabilityFlagsTransientConnection
when the VPN is connected, but I don't have a VPN, so I cannot test that claim. I'd suggest trying it with and without the VPN up and see if you get differentflags
returned.Unrelated to the problem at hand, your code sample will leak. If using ARC, don't forget to use
CFBridgingRelease
or__bridge_transfer
. Or regardless of whether in ARC or not, explicitly callCFRelease
before you return.If you run the static analyzer (press shift+command+B or choose "Analyze" from the "Product" menu) in recent versions of Xcode, it should warn you about the memory management of Core Foundation calls.
Anyway, this is how I'd be inclined to handle it in ARC:
- (BOOL)checkForVPNConnectivity { NSDictionary *dict = CFBridgingRelease(CFNetworkCopySystemProxySettings()); return [dict count] > 0; }
回答2:
You can use simple workaround for the above mentioned problem.
Just use apple reachability to check wherther ios device is connected to internet or not. If not throw no internet connection error.If yes,try to access your VPN dependant URL using NSURLConnection.If you get success 200 like that,i.e you are connected to VPN.If this request returns host not found or any error like -1001 means you are not connected to VPN.Then you can throw corresponding VPN connectivity error to the user.Happy coding.... Arun kumar
For more information please refer my blog http://aruntheiphonedeveloper.blogspot.in
回答3:
let connect=ConnectVPN()
connect.loadFromPreference()
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
let status=NEVPNManager.shared().connection.status
print(status)
}
Where load preference is
public func loadFromPreference(){
do {
try self.vpnManager.loadFromPreferences(completionHandler: {
error in
})
} catch let error {
print("Could not start VPN Connection: \(error.localizedDescription)" )
}
}
Then in status you get vpn status which is disconnected ,invalid and connected etc you can read about it from this link https://developer.apple.com/documentation/networkextension/nevpnstatus hope this will help you happy coding:)
来源:https://stackoverflow.com/questions/16285093/how-to-detect-iphones-vpn-connectivity