iOS开发中WiFi相关功能总结
http://www.cocoachina.com/ios/20160715/17022.html
投稿文章,作者:Haley_Wong(简书)
查漏补缺集是自己曾经做过相关的功能,但是重做相关功能或者重新看到相关功能的实现,感觉理解上更深刻。这一类的文章集中记录在查漏补缺集。
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";} |
iOS开发中WiFi相关功能总结的更多相关文章
- 深入理解iOS开发中的BitCode功能
前言 做iOS开发的朋友们都知道,目前最新的Xcode7,新建项目默认就打开了bitcode设置.而且大部分开发者都被这个突如其来的bitcode功能给坑过导致项目编译失败,而这些因为bitcode而 ...
- iOS开发中视图相关的小笔记:push、modal、popover、replace、custom
在storyboard中,segue有几种不同的类型,在iphone和ipad的开发中,segue的类型是不同的. 在iphone中,segue有:push,modal,和custom三种不同的类型, ...
- ios开发中的小技巧
在这里总结一些iOS开发中的小技巧,能大大方便我们的开发,持续更新. UITableView的Group样式下顶部空白处理 //分组列表头部空白处理 UIView *view = [[UIViewal ...
- iOS开发中获取WiFi相关信息
iOS 开发中难免会遇到很多与网络方面的判断,这里做个汇总,大多可能是与WiFi相关的. 1.Ping域名.Ping某IP 有 时候可能会遇到ping 某个域名或者ip通不通,再做下一步操作.这里的p ...
- iOS开发中打电话发短信等功能的实现
在APP开发中,可能会涉及到打电话.发短信.发邮件等功能.比如说,通常一个产品的"关于"页面,会有开发者的联系方式,理想情况下,当用户点击该电话号码时,能够自动的帮用户拨出去,就涉 ...
- iOS开发中文件的上传和下载功能的基本实现-备用
感谢大神分享 这篇文章主要介绍了iOS开发中文件的上传和下载功能的基本实现,并且下载方面讲到了大文件的多线程断点下载,需要的朋友可以参考下 文件的上传 说明:文件上传使用的时POST请求,通常把要上传 ...
- 多线程在iOS开发中的应用
多线程基本概念 01 进程 进程是指在系统中正在运行的一个应用程序.每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内. 02 线程 2-1 基本概念 1个进程要想执行任务,必须得有线程 ...
- 解析iOS开发中的FirstResponder第一响应对象
1. UIResonder 对于C#里所有的控件(例如TextBox),都继承于Control类.而Control类的继承关系如下: 代码如下: System.Object System.Marsha ...
- 在iOS开发中使用FMDB
在iOS开发中使用FMDB 前言 SQLite (http://www.sqlite.org/docs.html) 是一个轻量级的关系数据库.iOS SDK 很早就支持了 SQLite,在使用时,只需 ...
随机推荐
- 几种远程调用接口协议简单比较和web service(SOAP)与HTTP接口的区别:
什么是web service? 答:soap请求是HTTP POST的一个专用版本,遵循一种特殊的xml消息格式Content-type设置为: text/xml任何数据都可以xml化. ...
- 排列组合lucas模板
//codeforces 559C|51nod1486 Gerald and Giant Chess(组合数学+逆元) #include <bits/stdc++.h> using nam ...
- [转]C#中的委托和事件(续)
源码下载:http://www.tracefact.net/SourceCode/MoreDelegate.rar C#中的委托和事件(续) 引言 如果你看过了 C#中的委托和事件 一文,我想你对委托 ...
- Python-爬虫实战 简单爬取豆瓣top250电影保存到本地
爬虫原理 发送数据 获取数据 解析数据 保存数据 requests请求库 res = requests.get(url="目标网站地址") 获取二进制流方法:res.content ...
- python 连接mssql数据库
1.目标数据sql2008 R2 ComPrject=>TestModel 2.安装python 连接mssql 模块 运行 pip install pymssql-2.2.0.dev0-cp3 ...
- 原生微信小程序的生命周期
小程序的生命周期函数:onLaunch:function(){当启动小程序时触发小程序只会启动1次,一般为初次打开时一般只会触发一次},onShow:function(){当小程序从后台切入到前台时触 ...
- NSIS使用WinVer.nsh头文件判断操作系统版本
NSIS使用WinVer.nsh头文件判断操作系统版本,首先请下载最新的WinVer.nsh: http://nsis.sourceforge.net/Include/WinVer.nsh(下载后置于 ...
- 使用gRPC-Gateway快速构建微服务-双向认证下rpc-gateway使用(同时提供rpc和http接口)
https://github.com/grpc-ecosystem/grpc-gateway 在grpc之上加一层代理并转发,转变成protobuf格式来访问grpc服务 安装 go get -u g ...
- pycharm professional 2019版长效激活
PyCharm是一种Python IDE,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试.语法高亮.Project管理.代码跳转.智能提示.自动完成.单元测试.版本控制. ...
- JDBC工具类-DButils(QueryRunner-ResultSetHandler)
简述: DBUtils是Java编程中的数据库操作实用工具,小巧简单实用. DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码. DBUtils三个核心功能: QUeryRunne ...