设为首页 收藏本站
查看: 1078|回复: 0

[经验分享] 关于在iOS设备上探测WIFI,3G,GPRS使用情况的细节

[复制链接]

尚未签到

发表于 2015-10-1 07:18:08 | 显示全部楼层 |阅读模式
  转自:http://blog.iyunv.com/devfun/article/details/7365774
  由于设计的游戏需要有一些联网请求,但有时候在设备未连接网络的情况下,如果对网络情况不加以判断,则可能造成游戏为了等游戏超时,浪费不必要的时间。
  所以在游戏启动时检测一下网络状况是很必要的,而且当玩家的设备连接上网络以后,有一个回调函数也是非常必要的一件事儿,这样可能更方便我们在后台下载数据库等信息。

  apple为我们提供了一套范例代码,下面我就来分析一下这段代码。
范例代码地址在:https://developer.apple.com/library/ios/#samplecode/Reachability/Listings/Classes_ReachabilityAppDelegate_m.html#//apple_ref/doc/uid/DTS40007324-Classes_ReachabilityAppDelegate_m-DontLinkElementID_4
  
  范例中包含两部分,一部分是appdelegate,一部分是reachability



  1 #import <sys/socket.h>
  2 #import <netinet/in.h>
  3 #import <netinet6/in6.h>
  4 #import <arpa/inet.h>
  5 #import <ifaddrs.h>
  6 #import <netdb.h>
  7  
  8 #import <CoreFoundation/CoreFoundation.h>
  9  
10 #import "Reachability.h"
11  
12 #define kShouldPrintReachabilityFlags 1
13  
14 static void PrintReachabilityFlags(SCNetworkReachabilityFlags    flags, const char* comment)
15 {
16 #if kShouldPrintReachabilityFlags
17     
18     NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
19             (flags & kSCNetworkReachabilityFlagsIsWWAN)               ? 'W' : '-',//当前网络为蜂窝网络,即3G或者GPRS
20             (flags & kSCNetworkReachabilityFlagsReachable)            ? 'R' : '-',//网络请求地址可达
21            
22             (flags & kSCNetworkReachabilityFlagsTransientConnection)  ? 't' : '-',
23             (flags & kSCNetworkReachabilityFlagsConnectionRequired)   ? 'c' : '-',
24             (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic)  ? 'C' : '-',
25             (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
26             (flags & kSCNetworkReachabilityFlagsConnectionOnDemand)   ? 'D' : '-',
27             (flags & kSCNetworkReachabilityFlagsIsLocalAddress)       ? 'l' : '-',//该值为一个本地地址
28             (flags & kSCNetworkReachabilityFlagsIsDirect)             ? 'd' : '-',
29             comment
30             );
31 #endif
32 }
33  
34  
35 @implementation Reachability
36 static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
37 {
38     #pragma unused (target, flags)
39     NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
40     NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
41  
42     //We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively
43     // in case someon uses the Reachablity object in a different thread.
44     NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init];
45     
46     Reachability* noteObject = (Reachability*) info;
47     // Post a notification to notify the client that the network reachability changed.
48     [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
49     
50     [myPool release];
51 }
52
53
54
55 //启动探测网络
56 - (BOOL) startNotifier
57 {
58     BOOL retVal = NO;
59     SCNetworkReachabilityContext    context = {0, self, NULL, NULL, NULL};
60     //SCNetworkReachabilitySetCallback函数为指定一个target(此处为reachabilityRef,即www.apple.com,在reachabilityWithHostName里设置的)
61     //当设备对于这个target链接状态发生改变时(比如断开链接,或者重新连上),则回调reachabilityCallback函数,
62     if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
63     {
64         //指定一个runloop给指定的target
65         if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
66         {
67             retVal = YES;
68         }
69     }
70     return retVal;
71 }
72  //停止网络探测
73 - (void) stopNotifier
74 {
75     if(reachabilityRef!= NULL)
76     {
77         SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
78     }
79 }
80  
81 - (void) dealloc
82 {
83     [self stopNotifier];
84     if(reachabilityRef!= NULL)
85     {
86         CFRelease(reachabilityRef);
87     }
88     [super dealloc];
89 }
90  //通过域名设定一个目标地址比如www.apple.com
91 + (Reachability*) reachabilityWithHostName: (NSString*) hostName;
92 {
93     Reachability* retVal = NULL;
94     SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
95     if(reachability!= NULL)
96     {
97         retVal= [[[self alloc] init] autorelease];
98         if(retVal!= NULL)
99         {
100             retVal->reachabilityRef = reachability;
101             retVal->localWiFiRef = NO;
102         }
103     }
104     return retVal;
105 }
106   //通过ip地址设定一个目标的地址,可以加端口号,貌似我实验的不太成功
107 + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
108 {
109     SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
110     Reachability* retVal = NULL;
111     if(reachability!= NULL)
112     {
113         retVal= [[[self alloc] init] autorelease];
114         if(retVal!= NULL)
115         {
116             retVal->reachabilityRef = reachability;
117             retVal->localWiFiRef = NO;
118         }
119     }
120     return retVal;
121 }
122  //检测当前网络能否连上internet
123 + (Reachability*) reachabilityForInternetConnection;
124 {
125     struct sockaddr_in zeroAddress;
126     bzero(&zeroAddress, sizeof(zeroAddress));
127     zeroAddress.sin_len = sizeof(zeroAddress);
128     zeroAddress.sin_family = AF_INET;
129     return [self reachabilityWithAddress: &zeroAddress];
130 }
131  //检测当前网络是否能够连上本地wifi
132 + (Reachability*) reachabilityForLocalWiFi;
133 {
134     struct sockaddr_in localWifiAddress;
135     bzero(&localWifiAddress, sizeof(localWifiAddress));
136     localWifiAddress.sin_len = sizeof(localWifiAddress);
137     localWifiAddress.sin_family = AF_INET;
138     // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
139     localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
140     Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress];
141     if(retVal!= NULL)
142     {
143         retVal->localWiFiRef = YES;
144     }
145     return retVal;
146 }
147  
148 #pragma mark Network Flag Handling
149  
150 - (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags
151 {
152     PrintReachabilityFlags(flags, "localWiFiStatusForFlags");
153  
154     BOOL retVal = NotReachable;
155     if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
156     {
157         retVal = ReachableViaWiFi;  
158     }
159     return retVal;
160 }
161  //通过flags返回当前网络状态
162 - (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags
163 {
164     PrintReachabilityFlags(flags, "networkStatusForFlags");
165     if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
166     {
167         // if target host is not reachable
168         return NotReachable;
169     }
170  
171     BOOL retVal = NotReachable;
172     
173     if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
174     {
175         // if target host is reachable and no connection is required
176         //  then we'll assume (for now) that your on Wi-Fi
177         retVal = ReachableViaWiFi;
178     }
179     
180     
181     if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
182         (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
183     {
184             // ... and the connection is on-demand (or on-traffic) if the
185             //     calling application is using the CFSocketStream or higher APIs
186  
187             if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
188             {
189                 // ... and no [user] intervention is needed
190                 retVal = ReachableViaWiFi;
191             }
192         }
193     
194     if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
195     {
196         // ... but WWAN connections are OK if the calling application
197         //     is using the CFNetwork (CFSocketStream?) APIs.
198         retVal = ReachableViaWWAN;
199     }
200     return retVal;
201 }
202  
203 - (BOOL) connectionRequired;
204 {
205     NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
206     SCNetworkReachabilityFlags flags;
207     if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
208     {
209         return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
210     }
211     return NO;
212 }
213  //获得当前网络状态
214 - (NetworkStatus) currentReachabilityStatus
215 {
216     NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef");
217     NetworkStatus retVal = NotReachable;
218     SCNetworkReachabilityFlags flags;
219     if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
220     {
221         if(localWiFiRef)
222         {
223             retVal = [self localWiFiStatusForFlags: flags];
224         }
225         else
226         {
227             retVal = [self networkStatusForFlags: flags];
228         }
229     }
230     return retVal;
231 }
232 @end
  以上的部分为具体实现的部分,下面我们再来看在appdelegate里面调用的部分



- (void) applicationDidFinishLaunching: (UIApplication* )application
{
#pragma unused(application)
contentView.backgroundColor = [UIColor groupTableViewBackgroundColor];
summaryLabel.hidden = YES;        

//这句是设定一个回调函数reachability,当网络条件发生变化时则去调用reachabilityChanged
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(reachabilityChanged:) name: kReachabilityChangedNotification object: nil];
//Change the host name here to change the server your monitoring
remoteHostLabel.text = [NSString stringWithFormat: @"Remote Host: %@", @"www.apple.com"];
//设定target地址,这里是www.apple.com
hostReach = [[Reachability reachabilityWithHostName: @"www.apple.com"] retain];
//启动网络条件检测
    [hostReach startNotifier];
//更新UI的网络状态显示
    [self updateInterfaceWithReachability: hostReach];
//探测是否能连上internet网
internetReach = [[Reachability reachabilityForInternetConnection] retain];
[internetReach startNotifier];
[self updateInterfaceWithReachability: internetReach];
//探测wifi是否开启
wifiReach = [[Reachability reachabilityForLocalWiFi] retain];
[wifiReach startNotifier];
[self updateInterfaceWithReachability: wifiReach];
[window makeKeyAndVisible];
}


//如需要查看网络状态,如下调用即可
NetworkStatus netStatus = [curReach currentReachabilityStatus];
netStatus有ReachableViaWWAN(蜂窝网络3G之类的),ReachableViaWiFi(wifi连接),NotReachable(无法连接)
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-121071-1-1.html 上篇帖子: win 8 虚拟wifi bat 下篇帖子: [OpenWRT]Scan WIFI
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表