iOS开发中WiFi相关功能总结

简介: 1.Ping域名、Ping某IP 有时候可能会遇到ping 某个域名或者ip通不通,再做下一步操作。这里的ping与传统的做get或者post请求还是有很大区别的。比如我们连接了某个WiFi,测试ping www.baidu.com,如果能ping 通,基本可以断定可以上网了,但是如果我们做了一个get 请求(url 是www.baidu.com),路由器可能重定



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

727768-ff8ab7124905812e.jpg

PingTest效果图

727768-6d4c781945dd1334.jpg

终端ping效果图

2.获取WiFi信息

以前物联网刚火的时候,出现过很多一体式无线路由,所以App里难免会遇到要判断当前所连接的WiFi,以及获取WiFi信息的功能。13年的时候查过一些关于WiFi的方法,后面渐渐都忘记了。惭愧!!!

需要添加SystemConfiguration.framework 并在当前类中添加代码

#import arpa/inet.h>
#import netinet/in.h>
#import ifaddrs.h>

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






目录
相关文章
|
1天前
|
编解码 Android开发 iOS开发
深入探索Android与iOS开发的差异与挑战
【6月更文挑战第24天】在移动应用开发的广阔舞台上,Android和iOS两大操作系统扮演着主角。它们各自拥有独特的开发环境、工具集、用户基础及市场策略。本文将深度剖析这两个平台的开发差异,并探讨开发者面临的挑战,旨在为即将踏入或已在移动开发领域奋斗的开发者提供一份实用指南。
18 13
|
4天前
|
iOS开发 开发者 容器
探索iOS开发中的SwiftUI框架
【6月更文挑战第21天】本文深入探讨了苹果在iOS开发中推出的SwiftUI框架,旨在为开发者提供一种声明式、更简洁的界面设计方法。文章首先概述了SwiftUI的核心概念和优势,接着通过一个天气预报应用实例,详细讲解了如何使用SwiftUI进行布局和用户界面的设计。此外,还讨论了SwiftUI与UIKit的差异,以及如何将SwiftUI集成到现有的项目中。最后,文章展望了SwiftUI的未来发展方向,包括潜在的改进和新特性。
|
4天前
|
Java 开发工具 Android开发
安卓与iOS开发差异解析
【6月更文挑战第21天】本文旨在深入探讨安卓和iOS两大移动操作系统在应用开发过程中的主要差异。通过对比分析,揭示各自的设计哲学、编程语言选择、用户界面构建、性能优化策略以及发布流程的异同。文章将提供开发者视角下的实用信息,帮助他们更好地理解各自平台的特点和挑战,从而做出更明智的开发决策。
|
5天前
|
Java 开发工具 Android开发
探索安卓与iOS开发的核心差异
【6月更文挑战第20天】在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文将深入探讨这两大操作系统在开发过程中的主要区别,包括编程语言、开发工具、用户界面设计哲学、系统架构以及市场分布等方面。通过对这些关键差异的分析,旨在为开发者提供一份实用的指南,帮助他们在面对项目决策时,能够更加明智地选择合适的平台,并针对特定平台优化他们的应用。
|
5天前
|
开发工具 Android开发 iOS开发
探索安卓与iOS开发的差异:从工具到用户体验
【6月更文挑战第20天】在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文将深入探讨这两个操作系统在开发环境、编程语言、用户界面设计以及性能优化等方面的关键差异。我们将通过比较分析,揭示各自平台的独特优势和面临的挑战,为开发者提供决策参考,并为最终用户提供更深层次的用户体验洞察。
|
7天前
|
Java Android开发 Swift
探索Android与iOS开发的差异:平台选择对项目成功的影响
【6月更文挑战第18天】在移动应用开发的广阔天地中,Android和iOS两大平台各据一方,它们在市场份额、用户群体及开发环境上各有千秋。本文将深入分析这两个操作系统的开发差异,探讨如何根据项目需求选择合适的平台,并讨论跨平台解决方案的可行性与挑战。我们将通过实际案例,揭示平台选择对项目成功的关键性影响,为开发者提供决策支持。
|
7天前
|
Swift iOS开发 开发者
探索iOS开发中的SwiftUI框架
在苹果的生态系统中,SwiftUI代表了iOS应用开发的一次重大飞跃。作为一项现代化的UI工具集,它旨在简化和加速界面设计过程,同时确保代码的清晰度与可维护性。本文将深入探讨SwiftUI的核心概念、优势以及在实际开发中的应用案例,为开发者提供全面而实用的指南。
|
8天前
|
安全 IDE Android开发
探索Android与iOS开发的差异:平台特性与编程实践
【6月更文挑战第17天】在移动应用开发的广阔天地中,Android和iOS两大平台各自占据半壁江山。它们在用户群体、系统架构以及开发环境上的差异,为开发者带来了不同的挑战和机遇。本文深入探讨了这两个平台在技术实现、界面设计、性能优化等方面的主要区别,并提供了实用的开发建议,旨在帮助开发者更好地理解各自平台的特性,从而创造出更加优秀的移动应用。
|
11天前
|
安全 Android开发 iOS开发
探索Android与iOS开发的差异:平台特性与用户体验的对比分析
在移动应用开发的广阔天地中,Android和iOS两大阵营各据一方。本文将深入探讨这两个操作系统在开发环境、编程语言、用户界面设计及市场分布等方面的主要区别。通过比较分析,我们将揭示各自平台的特有优势,并讨论如何根据目标受众和业务需求选择适合的开发平台。
|
11天前
|
iOS开发 开发者
探索iOS开发中的SwiftUI框架
【6月更文挑战第14天】本文将深入探讨iOS开发领域的新星——SwiftUI框架。我们将从其设计理念出发,逐步解析其结构与核心组件,并通过实例展示如何利用SwiftUI简化界面构建流程,提升开发效率。同时,我们也将讨论SwiftUI在现有项目中的集成策略及其对iOS应用开发未来的可能影响。
20 1