Reachability.h
1 /* 2 3 File: Reachability.h 4 Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. 5 6 Version: 2.2 7 8 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. 9 ("Apple") in consideration of your agreement to the following terms, and your 10 use, installation, modification or redistribution of this Apple software 11 constitutes acceptance of these terms. If you do not agree with these terms, 12 please do not use, install, modify or redistribute this Apple software. 13 14 In consideration of your agreement to abide by the following terms, and subject 15 to these terms, Apple grants you a personal, non-exclusive license, under 16 Apple's copyrights in this original Apple software (the "Apple Software"), to 17 use, reproduce, modify and redistribute the Apple Software, with or without 18 modifications, in source and/or binary forms; provided that if you redistribute 19 the Apple Software in its entirety and without modifications, you must retain 20 this notice and the following text and disclaimers in all such redistributions 21 of the Apple Software. 22 Neither the name, trademarks, service marks or logos of Apple Inc. may be used 23 to endorse or promote products derived from the Apple Software without specific 24 prior written permission from Apple. Except as expressly stated in this notice, 25 no other rights or licenses, express or implied, are granted by Apple herein, 26 including but not limited to any patent rights that may be infringed by your 27 derivative works or by other works in which the Apple Software may be 28 incorporated. 29 30 The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO 31 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED 32 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN 34 COMBINATION WITH YOUR PRODUCTS. 35 36 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR 37 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 38 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR 40 DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF 41 CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF 42 APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 44 Copyright (C) 2010 Apple Inc. All Rights Reserved. 45 46 */ 47 48 49 #import <Foundation/Foundation.h> 50 #import <SystemConfiguration/SystemConfiguration.h> 51 52 typedef enum { 53 NotReachable = 0, 54 ReachableViaWiFi, 55 ReachableViaWWAN 56 } NetworkStatus; 57 #define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification" 58 59 @interface Reachability: NSObject 60 { 61 BOOL localWiFiRef; 62 SCNetworkReachabilityRef reachabilityRef; 63 } 64 65 //reachabilityWithHostName- Use to check the reachability of a particular host name. 66 + (Reachability*) reachabilityWithHostName: (NSString*) hostName; 67 68 //reachabilityWithAddress- Use to check the reachability of a particular IP address. 69 + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; 70 71 //reachabilityForInternetConnection- checks whether the default route is available. 72 // Should be used by applications that do not connect to a particular host 73 + (Reachability*) reachabilityForInternetConnection; 74 75 //reachabilityForLocalWiFi- checks whether a local wifi connection is available. 76 + (Reachability*) reachabilityForLocalWiFi; 77 78 //Start listening for reachability notifications on the current run loop 79 - (BOOL) startNotifier; 80 - (void) stopNotifier; 81 82 - (NetworkStatus) currentReachabilityStatus; 83 //WWAN may be available, but not active until a connection has been established. 84 //WiFi may require a connection for VPN on Demand. 85 - (BOOL) connectionRequired; 86 @end
Reachability.m
1 /* 2 3 File: Reachability.m 4 Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. 5 6 Version: 2.2 7 8 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. 9 ("Apple") in consideration of your agreement to the following terms, and your 10 use, installation, modification or redistribution of this Apple software 11 constitutes acceptance of these terms. If you do not agree with these terms, 12 please do not use, install, modify or redistribute this Apple software. 13 14 In consideration of your agreement to abide by the following terms, and subject 15 to these terms, Apple grants you a personal, non-exclusive license, under 16 Apple's copyrights in this original Apple software (the "Apple Software"), to 17 use, reproduce, modify and redistribute the Apple Software, with or without 18 modifications, in source and/or binary forms; provided that if you redistribute 19 the Apple Software in its entirety and without modifications, you must retain 20 this notice and the following text and disclaimers in all such redistributions 21 of the Apple Software. 22 Neither the name, trademarks, service marks or logos of Apple Inc. may be used 23 to endorse or promote products derived from the Apple Software without specific 24 prior written permission from Apple. Except as expressly stated in this notice, 25 no other rights or licenses, express or implied, are granted by Apple herein, 26 including but not limited to any patent rights that may be infringed by your 27 derivative works or by other works in which the Apple Software may be 28 incorporated. 29 30 The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO 31 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED 32 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN 34 COMBINATION WITH YOUR PRODUCTS. 35 36 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR 37 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 38 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR 40 DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF 41 CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF 42 APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 44 Copyright (C) 2010 Apple Inc. All Rights Reserved. 45 46 */ 47 48 #import <sys/socket.h> 49 #import <netinet/in.h> 50 #import <netinet6/in6.h> 51 #import <arpa/inet.h> 52 #import <ifaddrs.h> 53 #import <netdb.h> 54 55 #import <CoreFoundation/CoreFoundation.h> 56 57 #import "Reachability.h" 58 59 #define kShouldPrintReachabilityFlags 1 60 61 static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment) 62 { 63 #if kShouldPrintReachabilityFlags 64 65 NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s ", 66 (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', 67 (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', 68 69 (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', 70 (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', 71 (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', 72 (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', 73 (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', 74 (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', 75 (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-', 76 comment 77 ); 78 #endif 79 } 80 81 82 @implementation Reachability 83 static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, id info) 84 { 85 #pragma unused (target, flags) 86 NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback"); 87 NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback"); 88 89 //We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively 90 // in case someon uses the Reachablity object in a different thread. 91 92 Reachability* noteObject = (Reachability*) info; 93 // Post a notification to notify the client that the network reachability changed. 94 [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject]; 95 96 } 97 98 - (BOOL) startNotifier 99 { 100 BOOL retVal = NO; 101 SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL}; 102 if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)) 103 { 104 if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) 105 { 106 retVal = YES; 107 } 108 } 109 return retVal; 110 } 111 112 - (void) stopNotifier 113 { 114 if(reachabilityRef!= NULL) 115 { 116 SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); 117 } 118 } 119 120 121 + (Reachability*) reachabilityWithHostName: (NSString*) hostName; 122 { 123 Reachability* retVal = NULL; 124 SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]); 125 if(reachability!= NULL) 126 { 127 retVal= [[self alloc] init]; 128 if(retVal!= NULL) 129 { 130 retVal->reachabilityRef = reachability; 131 retVal->localWiFiRef = NO; 132 } 133 } 134 return retVal; 135 } 136 137 + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; 138 { 139 SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress); 140 Reachability* retVal = NULL; 141 if(reachability!= NULL) 142 { 143 retVal= [[self alloc] init]; 144 if(retVal!= NULL) 145 { 146 retVal->reachabilityRef = reachability; 147 retVal->localWiFiRef = NO; 148 } 149 } 150 return retVal; 151 } 152 153 + (Reachability*) reachabilityForInternetConnection; 154 { 155 struct sockaddr_in zeroAddress; 156 bzero(&zeroAddress, sizeof(zeroAddress)); 157 zeroAddress.sin_len = sizeof(zeroAddress); 158 zeroAddress.sin_family = AF_INET; 159 return [self reachabilityWithAddress: &zeroAddress]; 160 } 161 162 + (Reachability*) reachabilityForLocalWiFi; 163 { 164 struct sockaddr_in localWifiAddress; 165 bzero(&localWifiAddress, sizeof(localWifiAddress)); 166 localWifiAddress.sin_len = sizeof(localWifiAddress); 167 localWifiAddress.sin_family = AF_INET; 168 // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0 169 localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); 170 Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress]; 171 if(retVal!= NULL) 172 { 173 retVal->localWiFiRef = YES; 174 } 175 return retVal; 176 } 177 178 #pragma mark Network Flag Handling 179 180 - (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags 181 { 182 PrintReachabilityFlags(flags, "localWiFiStatusForFlags"); 183 184 BOOL retVal = NotReachable; 185 if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect)) 186 { 187 retVal = ReachableViaWiFi; 188 } 189 return retVal; 190 } 191 192 - (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags 193 { 194 PrintReachabilityFlags(flags, "networkStatusForFlags"); 195 if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) 196 { 197 // if target host is not reachable 198 return NotReachable; 199 } 200 201 BOOL retVal = NotReachable; 202 203 if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) 204 { 205 // if target host is reachable and no connection is required 206 // then we'll assume (for now) that your on Wi-Fi 207 retVal = ReachableViaWiFi; 208 } 209 210 211 if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || 212 (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) 213 { 214 // ... and the connection is on-demand (or on-traffic) if the 215 // calling application is using the CFSocketStream or higher APIs 216 217 if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) 218 { 219 // ... and no [user] intervention is needed 220 retVal = ReachableViaWiFi; 221 } 222 } 223 224 if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) 225 { 226 // ... but WWAN connections are OK if the calling application 227 // is using the CFNetwork (CFSocketStream?) APIs. 228 retVal = ReachableViaWWAN; 229 } 230 return retVal; 231 } 232 233 - (BOOL) connectionRequired; 234 { 235 NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef"); 236 SCNetworkReachabilityFlags flags; 237 if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 238 { 239 return (flags & kSCNetworkReachabilityFlagsConnectionRequired); 240 } 241 return NO; 242 } 243 244 - (NetworkStatus) currentReachabilityStatus 245 { 246 NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef"); 247 NetworkStatus retVal = NotReachable; 248 SCNetworkReachabilityFlags flags; 249 if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags)) 250 { 251 if(localWiFiRef) 252 { 253 retVal = [self localWiFiStatusForFlags: flags]; 254 } 255 else 256 { 257 retVal = [self networkStatusForFlags: flags]; 258 } 259 } 260 return retVal; 261 } 262 @end
将Reachability.h 和 Reachability.m 加到自己的项目中,并引用 SystemConfiguration.framework。
1 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 2 { 3 4 self.helper = [Helper Instance]; 5 6 //开启网络状况的监听 7 [[NSNotificationCenter defaultCenter] addObserver:self 8 selector:@selector(reachabilityChanged:) 9 name: kReachabilityChangedNotification 10 object: nil]; 11 curReach = [Reachability reachabilityForInternetConnection]; 12 13 switch ([curReach currentReachabilityStatus]) 14 { 15 case NotReachable://没有网络 16 { 17 UIAlertView * av_error = [[UIAlertView alloc] initWithTitle:@"Title" message:@"无网络连接 无法加载数据" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; 18 [av_error show]; 19 break; 20 } 21 case ReachableViaWiFi://有wifi 22 case ReachableViaWWAN://有3G 23 { 24 } 25 default: 26 break; 27 } 28 29 [curReach startNotifier]; 30 [self updateInterfaceWithReachability: curReach]; 31 32 33 return YES; 34 } 35 36 // 连接改变 37 - (void) reachabilityChanged: (NSNotification* )note 38 { 39 Reachability* curReach = [note object]; 40 NSParameterAssert([curReach isKindOfClass: [Reachability class]]); 41 [self updateInterfaceWithReachability: curReach]; 42 } 43 44 //处理连接改变后的情况 45 - (void) updateInterfaceWithReachability: (Reachability*) curReach 46 { 47 //对连接改变做出响应的处理动作。 48 NetworkStatus status = [curReach currentReachabilityStatus]; 49 50 if (status == NotReachable) 51 { 52 ;//do something 53 } 54 else 55 { 56 ;//do otherthing 57 } 58 }