博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS开发中获取WiFi相关信息
阅读量:4611 次
发布时间:2019-06-09

本文共 8731 字,大约阅读时间需要 29 分钟。

iOS 开发中难免会遇到很多与网络方面的判断,这里做个汇总,大多可能是与WiFi相关的。

1.Ping域名、Ping某IP

有 时候可能会遇到ping 某个域名或者ip通不通,再做下一步操作。这里的ping与传统的做get或者post请求还是有很大区别的。比如我们连接了某个WiFi,测试ping www.baidu.com,如果能ping 通,基本可以断定可以上网了,但是如果我们做了一个get 请求(url 是www.baidu.com),路由器可能重定向这个WiFi内的某网页了,依然没有错误返回,就会误认为可以正常上网。

这里有关于ping命令的详细解释:

iOS中想要ping域名或者ip,苹果提供了一个官方例子

在例子中,有一个苹果已经封装过的类【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:}

这里有一个别人写的工程:

727768-ff8ab7124905812e.jpg

PingTest效果图

727768-6d4c781945dd1334.jpg

终端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"
;
}

 

转载于:https://www.cnblogs.com/xiguapijiamuguanaicha/p/5672454.html

你可能感兴趣的文章
OpenMobile's Application Compatibility Layer (ACL)
查看>>
竞价广告系统-广告检索
查看>>
[转]基于.NET平台常用的框架整理
查看>>
Symbian (Read Inbox)读取收件箱的内容
查看>>
Metro Style app :浏览器扩展
查看>>
linux的kernel是怎样工作的(TI_DM36X_ARM系统)(1)
查看>>
[luogu4310] 绝世好题 (递推)
查看>>
[luogu3203 HNOI2010] 弹飞绵羊 (分块)
查看>>
mui搜索框 搜索点击事件
查看>>
超链接样式设置(去下划线)(转)
查看>>
2016012003+陈琦+散列函数的应用及其安全性
查看>>
Android 状态栏通知Notification、NotificationManager详解
查看>>
UIApplicationDelegate协议
查看>>
Jmeter测试dubbo接口填坑
查看>>
[zz]GDB调试精粹及使用实例
查看>>
数据库的创建和删除
查看>>
最简单的三层实例【插入据
查看>>
设计模式学习笔记——Prototype原型模式
查看>>
pom.xml里有红叉报错的解决办法
查看>>
Perl last和next的用法区别
查看>>