我需要以编程方式检测iphone是否连接到VPN。我正在开发一个尝试加载URL的应用程序,此页面仅在设备连接到VPN时打开。在加载此URL之前,我需要检查VPN连接。我尝试了以下内容。但这并没有像预期的那样发挥作用。
- (BOOL)checkForVPNConnectivity {
NSDictionary *dict = (__bridge NSDictionary *)(CFNetworkCopySystemProxySettings());
//NSLog(@"cfnetwork proxy setting : %@", dict);
return [dict count] > 0;
}
答案 0 :(得分:4)
我不认为应该通过检查CFNetworkCopySystemProxySettings()
中的非零数量的元素来确定VPN连接。 (例如,我在WiFi网络上看到条目,但在VPN上看不到。)
所以,有两个观察结果:
我会考虑使用SystemConfiguration.framework
并将以下代码与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;
}
}
假设success
非零,您可能需要对flags
中位的设置进行一些实证研究。有关这些标志的技术定义,请参阅SCNetworkReachability Reference。我已经听说过在VPN连接时他们得到kSCNetworkReachabilityFlagsReachable | kSCNetworkReachabilityFlagsTransientConnection
,但我没有VPN,所以我无法测试这个说法。我建议尝试使用和不使用VPN,并查看是否返回了不同的flags
。
与手头的问题无关,您的代码示例会泄漏。如果使用ARC,请不要忘记使用CFBridgingRelease
或__bridge_transfer
。或者无论是否在ARC中,在返回之前明确地调用CFRelease
。
如果您运行静态分析仪(按 shift + 命令 + B 或选择"分析"来自& #34;产品"菜单)在Xcode的最新版本中,它应该警告你关于Core Foundation调用的内存管理。
无论如何,这就是我倾向于在ARC中处理它的方式:
- (BOOL)checkForVPNConnectivity
{
NSDictionary *dict = CFBridgingRelease(CFNetworkCopySystemProxySettings());
return [dict count] > 0;
}
答案 1 :(得分:0)
您可以针对上述问题使用简单的解决方法。
只需使用apple reachability检查ios设备是否已连接到互联网。如果没有丢失互联网连接错误。如果是,请尝试使用NSURLConnection访问您的VPN依赖URL。如果您获得成功200,即您连接到VPN。如果此请求返回主机未找到或任何错误,如-1001意味着您没有连接到VPN。然后您可以向用户抛出相应的VPN连接错误。快乐编码.... Arun kumar
有关更多信息,请参阅我的博客 http://aruntheiphonedeveloper.blogspot.in
答案 2 :(得分:0)
let connect=ConnectVPN()
connect.loadFromPreference()
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
let status=NEVPNManager.shared().connection.status
print(status)
}
负载偏好为
public func loadFromPreference(){
do {
try self.vpnManager.loadFromPreferences(completionHandler: {
error in
})
} catch let error {
print("Could not start VPN Connection: \(error.localizedDescription)" )
}
}
然后处于状态,您将获得已断开连接,无效和已连接等的vpn状态,您可以通过此链接查看https://developer.apple.com/documentation/networkextension/nevpnstatus 希望对你有帮助 快乐的编码:)
答案 3 :(得分:0)
简单使用这个方法你就可以实现。 自 iOS 12 和 iOS 13 以来,密钥列表已更改
已添加 2 个键
utun1 和 utun2
所以函数应该是:
static func isConnectedToVPN() -> Bool {
let cfDict = CFNetworkCopySystemProxySettings()
let nsDict = cfDict!.takeRetainedValue() as NSDictionary
let keys = nsDict["__SCOPED__"] as! NSDictionary
for key: String in keys.allKeys as! [String] {
if (key == "tap" || key == "tun" || key == "ppp" || key == "ipsec" || key == "ipsec0" || key == "utun1" || key == "utun2") {
return true
}
}
return false
}