查漏补缺集是自己曾经做过相关的功能,但是重做相关功能或者重新看到相关功能的实现,感觉理解上更深刻。这一类的文章集中记录在查漏补缺集。
iOS 开发中难免会遇到很多与网络方面的判断,这里做个汇总,大多可能是与WiFi相关的。
1.Ping域名、Ping某IP
有时候可能会遇到ping 某个域名或者ip通不通,再做下一步操作。这里的ping与传统的做get或者post请求还是有很大区别的。比如我们连接了某个WiFi,测试ping www.baidu.com,如果能ping 通,基本可以断定可以上网了,但是如果我们做了一个get 请求(url 是www.baidu.com),路由器可能重定向这个WiFi内的某网页了,依然没有错误返回,就会误认为可以正常上网。
这里有关于ping命令的详细解释:百度百科Ping
iOS中想要ping域名或者ip,苹果提供了一个官方例子SimplePing
在例子中,有一个苹果已经封装过的类【SimplePing.h】和【SimplePing.m】
使用起来也相当的简单:
首先创建一个Ping对象:
1
2
3
4
5
|
SimplePing *pinger = [[SimplePing alloc] initWithHostName:self.hostName];
self.pinger = pinger;
pinger.delegate = self;
pinger.addressStyle = SimplePingAddressStyleICMPv4;
[pinger start];
|
然后在start成功的代理方法中,发送数据报文:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/** * start成功,也就是准备工作做完后的回调
*/
- (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address { // 发送测试报文数据
[self.pinger sendPingWithData:nil];
} - (void)simplePing:(SimplePing *)pinger didFailWithError:(NSError *)error { NSLog(@ "didFailWithError" );
[self.pinger stop];
} |
其他几个代理方法也非常简单,就简单记录一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// 发送测试报文成功的回调方法 - (void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber { NSLog(@ "#%u sent" , sequenceNumber);
} //发送测试报文失败的回调方法 - (void)simplePing:(SimplePing *)pinger didFailToSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber error:(NSError *)error { NSLog(@ "#%u send failed: %@" , sequenceNumber, error);
} // 接收到ping的地址所返回的数据报文回调方法 - (void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber { NSLog(@ "#%u received, size=%zu" , sequenceNumber, packet.length);
} - (void)simplePing:(SimplePing *)pinger didReceiveUnexpectedPacket:(NSData *)packet { NSLog(@ "#%s" ,__func__);
} |
注意点:
iOS 中 ping失败后(即发送测试报文成功后,一直没后收到响应的报文),不会有任何回调方法告知我们。而一般ping 一次的结果也不太准确,ping 花费的时间也非常短,所以我们一般会ping多次,发送一次ping 测试报文0.5s后检测一下这一次ping是否已经收到响应。0.5s后检测时,如果已经收到响应,则可以ping 通;如果没有收到响应,则视为超时。
做法也有很多种,可以用NSTimer或者 {- (void)performSelector: withObject:afterDelay:}
这里有一个别人写的工程:https://github.com/lovesunstar/STPingTest
PingTest效果图
终端ping效果图
2.获取WiFi信息
以前物联网刚火的时候,出现过很多一体式无线路由,所以App里难免会遇到要判断当前所连接的WiFi,以及获取WiFi信息的功能。13年的时候查过一些关于WiFi的方法,后面渐渐都忘记了。惭愧!!!
需要添加SystemConfiguration.framework 并在当前类中添加代码#import
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//获取WiFi 信息,返回的字典中包含了WiFi的名称、路由器的Mac地址、还有一个Data(转换成字符串打印出来是wifi名称) - (NSDictionary *)fetchSSIDInfo { NSArray *ifs = (__bridge_transfer NSArray *)CNCopySupportedInterfaces();
if (!ifs) {
return nil;
}
NSDictionary *info = nil;
for (NSString *ifnam in ifs) {
info = (__bridge_transfer NSDictionary *)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
if (info && [info count]) { break ; }
}
return info;
} //打印出来的结果: 2016-05-12 15:28:51.674 SimplePing[18883:6790207] WIFI_INFO:{ BSSID = "a4:2b:8c:c:7f:bd" ;
SSID = bdmy06;
SSIDDATA = ;
} |
3.获取WiFi名称
有了上一步,获取WiFi名称就非常简单了。
1
2
3
|
NSString *WiFiName = info[@ "SSID" ];
//打印结果: 2016-05-12 15:35:13.059 SimplePing[18887:6791418] bdmy06 |
完整的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
- (NSString *)fetchWiFiName { NSArray *ifs = (__bridge_transfer NSArray *)CNCopySupportedInterfaces();
if (!ifs) {
return nil;
}
NSString *WiFiName = nil;
for (NSString *ifnam in ifs) {
NSDictionary *info = (__bridge_transfer NSDictionary *)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
if (info && [info count]) {
// 这里其实对应的有三个key:kCNNetworkInfoKeySSID、kCNNetworkInfoKeyBSSID、kCNNetworkInfoKeySSIDData,
// 不过它们都是CFStringRef类型的
WiFiName = [info objectForKey:(__bridge NSString *)kCNNetworkInfoKeySSID];
// WiFiName = [info objectForKey:@"SSID"]; break ;
}
}
return WiFiName;
} |
4.获取当前所连接WiFi的网关地址
例如自己家的路由器一般默认的网关地址是192.168.1.1,获取的就是这个192.168.1.1。
为什么不直接写死呢?
因为一些商场或者有多个路由器的网关地址是不一样的,比如之前有个公司的网关是192.168.89.1。
这里有篇博客,这是地址
需要导入的库:
1
|
#import #import #import |
获取网关的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
- (NSString *)getGatewayIpForCurrentWiFi { NSString *address = @ "error" ;
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
//*/
while (temp_addr != NULL) {
/*/
int i=255;
while ((i--)>0)
//*/
if (temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@ "en0" ])
{
// Get NSString from C String //ifa_addr
//ifa->ifa_dstaddr is the broadcast address, which explains the "255's"
// address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)];
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
//routerIP----192.168.1.255 广播地址
NSLog(@ "broadcast address--%@" ,[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)]);
//--192.168.1.106 本机地址
NSLog(@ "local device ip--%@" ,[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)]);
//--255.255.255.0 子网掩码地址
NSLog(@ "netmask--%@" ,[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_netmask)->sin_addr)]);
//--en0 端口地址
NSLog(@ "interface--%@" ,[NSString stringWithUTF8String:temp_addr->ifa_name]);
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
in_addr_t i = inet_addr([address cStringUsingEncoding:NSUTF8StringEncoding]);
in_addr_t* x = &i;
unsigned char *s = getdefaultgateway(x);
NSString *ip=[NSString stringWithFormat:@ "%d.%d.%d.%d" ,s[0],s[1],s[2],s[3]];
free(s);
return ip;
} |
其中 getdefaultgateway 是一个C语言文件中的方法,在工程里可以找到。
5.获取本机在WiFi环境下的IP地址
获取本机在WiFi环境下的ip地址,在上一节中其实已经写过,这里将其提取出来即可:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
- (NSString *)getLocalIPAddressForCurrentWiFi { NSString *address = nil;
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while (temp_addr != NULL) {
if (temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@ "en0" ]) {
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
return address;
}
}
temp_addr = temp_addr->ifa_next;
}
freeifaddrs(interfaces);
}
return nil;
} |
同样的方式也可以获取广播地址、子网掩码、端口等,组装成一个字典。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
- (NSMutableDictionary *)getLocalInfoForCurrentWiFi { NSMutableDictionary *dict = [NSMutableDictionary dictionary];
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
//*/
while (temp_addr != NULL) {
if (temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@ "en0" ]) {
//----192.168.1.255 广播地址
NSString *broadcast = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)];
if (broadcast) {
[dict setObject:broadcast forKey:@ "broadcast" ];
}
NSLog(@ "broadcast address--%@" ,broadcast);
//--192.168.1.106 本机地址
NSString *localIp = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
if (localIp) {
[dict setObject:localIp forKey:@ "localIp" ];
}
NSLog(@ "local device ip--%@" ,localIp);
//--255.255.255.0 子网掩码地址
NSString *netmask = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_netmask)->sin_addr)];
if (netmask) {
[dict setObject:netmask forKey:@ "netmask" ];
}
NSLog(@ "netmask--%@" ,netmask);
//--en0 端口地址
NSString *interface = [NSString stringWithUTF8String:temp_addr->ifa_name];
if (interface) {
[dict setObject:interface forKey:@ "interface" ];
}
NSLog(@ "interface--%@" ,interface);
return dict;
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return dict;
} |
将返回的字典打印出来:
1
2
3
4
5
6
|
2016-05-12 17:59:09.257 SimplePing[19141:6830567] wifi:{ broadcast = "192.168.1.255" ;
interface = en0;
localIp = "192.168.1.7" ;
netmask = "255.255.255.0" ;
} |
相关推荐
总之,通过引入`SystemConfiguration.CaptiveNetwork`框架并使用相应的API,我们可以编写函数来获取iOS设备当前连接的WiFi的SSID和BSSID。但务必注意随着iOS版本更新,权限策略的变化,确保代码符合最新的隐私规定。
除了`Reachability`,还可以使用iOS内置的`SystemConfiguration`框架,尤其是`CaptiveNetwork`子框架,来检测WiFi连接的信息。`CaptiveNetwork`可以获取当前连接的WiFi热点信息,但不适用于检测蜂窝数据。以下是如何...
在iOS开发中,获取设备当前连接的网络类型是一项常见的需求,这有助于优化应用程序的行为,比如在WiFi环境下加载大文件,在移动网络下节省流量等。本文将详细讲解三种方法来检测iOS设备的网络状态,包括是否连接到...
P2P集线器-iOS / Swift 介绍 对下一个新的基于P2P的应用程序有想法吗? 这将使您的生活更轻松! 使用此集线器可以使用wifi-direct管理从一部iPhone到另一部iPhone的连接。 您可以轻松地建立新的连接并来回传输文本...
在iOS中,直接获取WiFi名字并不像Android那样直接提供API,因为Apple出于隐私考虑限制了这一功能。但可以通过访问`NEHotspotHelper`框架的代理方法间接获取。首先,你需要在`Info.plist`文件中添加使用网络扩展的...
以下是一个简单的Swift示例,使用SCNetworkReachability API来判断网络是否可用: ```swift import SystemConfiguration func checkInternetConnection() -> Bool { var zeroAddress = sockaddr_in(sin_len: 0, ...
Swift语言作为苹果官方推荐的开发语言,提供了丰富的API和工具来帮助开发者处理网络权限的监控和判断。本篇将深入探讨如何在Swift中有效地管理网络权限,并确保应用的安全性。 首先,我们需要理解iOS的网络访问策略...
7. 应用程序接口(API):为了使WiFi存储解决方案对开发者友好,通常会提供应用程序接口供第三方应用集成,这样可以简化开发流程,使用户可以借助第三方应用更便捷地访问和管理存储在WiFi存储上的数据。 在WiFi存储...
在iOS开发中,有时我们需要获取设备当前连接的...总之,获取iOS设备当前连接的WiFi信息主要依赖于`CaptiveNetwork`框架提供的API,但随着iOS版本的更新,开发者需要关注隐私政策的变化,以确保应用的合规性和用户体验。
此外,iOS 13及更高版本引入了`Network`框架,它提供了一个更现代且强大的API来处理网络监控。`NWPathMonitor`类可以用来监测网络路径的状态,包括WiFi、蜂窝数据等。 总结一下,检测iOS设备的网络状态主要包括以下...
在iOS和Android平台上,都有相应的API来帮助开发者获取设备的网络类型。本文将深入探讨如何在这些平台下判断手机的网络类型。 首先,我们来看iOS平台。在iOS中,Apple提供了Reachability框架,这个框架可以帮助我们...
首先,我们要了解iOS系统提供的网络状态检测API。苹果的Foundation框架中提供了Reachability类,这是一个实用工具,用于检测设备当前的网络可达性。 Reachability类可以检测到WiFi、蜂窝数据以及是否能够访问互联网...
《基于WiFi的室内定位系统在iOS7中的应用详解》 在现代科技的推动下,室内定位技术已经成为智能手机应用的重要组成部分,特别是在大型购物中心、机场、医院等复杂环境内导航的需求日益增长。本文将深入探讨一款基于...
在iOS开发中,获取WiFi列表则需要使用CoreWLAN框架。以下是一个Swift示例: ```swift import CoreWLAN let cwManager = CWInterface() cwManager.scanForNetworks { (networks, error) in if let networks = ...
例如,当设备连接到WiFi时,会显示WiFi图标;连接到蜂窝数据时,则会显示4G、3G或E等标识。我们可以通过观察这个状态栏图标来判断网络状态。不过,这种方法的局限性在于它只能获取到网络连接的大致类型,无法得知...
AF.request("https://api.example.com/data").responseJSON { response in switch response.result { case .success(let data): // 处理成功返回的数据 print("Received data: \(data)") case .failure(let ...
本文将深入探讨如何在iOS系统中获取网络类型,主要包括WIFI、2G、3G等不同网络环境的识别。我们将分析两种常用的方法,并讨论它们的优缺点。 首先,我们来看第一种方法,它利用了iOS系统的私有API来获取网络类型。...
在iOS 4.1及以上版本,苹果提供了一个API `CNCopyCurrentNetworkInfo` 来获取当前连接的WiFi信息。以下是一个简单的示例代码: ```objc + (NSString *)wifiSSID { NSString *ssid = nil; NSArray *ifs = (__...