ios检测网络连接状态

时间:2022-02-21 23:52:48

使用Reachability检测网络连接状态

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 
58 #define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification"
59 
60 @interface Reachability: NSObject
61 {
62     BOOL localWiFiRef;
63     SCNetworkReachabilityRef reachabilityRef;
64 }
65 
66 //reachabilityWithHostName- Use to check the reachability of a particular host name.
67 + (Reachability*) reachabilityWithHostName: (NSString*) hostName;
68 
69 //reachabilityWithAddress- Use to check the reachability of a particular IP address.
70 + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
71 
72 //reachabilityForInternetConnection- checks whether the default route is available.
73 //  Should be used by applications that do not connect to a particular host
74 + (Reachability*) reachabilityForInternetConnection;
75 
76 //reachabilityForLocalWiFi- checks whether a local wifi connection is available.
77 + (Reachability*) reachabilityForLocalWiFi;
78 
79 //Start listening for reachability notifications on the current run loop
80 - (BOOL) startNotifier;
81 - (void) stopNotifier;
82 
83 - (NetworkStatus) currentReachabilityStatus;
84 //WWAN may be available, but not active until a connection has been established.
85 //WiFi may require a connection for VPN on Demand.
86 - (BOOL) connectionRequired;
87 @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\n",
 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, void* 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     NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init];
 92     
 93     Reachability* noteObject = (Reachability*) info;
 94     // Post a notification to notify the client that the network reachability changed.
 95     [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
 96     
 97     [myPool release];
 98 }
 99 
100 - (BOOL) startNotifier
101 {
102     BOOL retVal = NO;
103     SCNetworkReachabilityContext    context = {0, self, NULL, NULL, NULL};
104     if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
105     {
106         if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
107         {
108             retVal = YES;
109         }
110     }
111     return retVal;
112 }
113 
114 - (void) stopNotifier
115 {
116     if(reachabilityRef!= NULL)
117     {
118         SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
119     }
120 }
121 
122 - (void) dealloc
123 {
124     [self stopNotifier];
125     if(reachabilityRef!= NULL)
126     {
127         CFRelease(reachabilityRef);
128     }
129     [super dealloc];
130 }
131 
132 + (Reachability*) reachabilityWithHostName: (NSString*) hostName;
133 {
134     Reachability* retVal = NULL;
135     SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
136     if(reachability!= NULL)
137     {
138         retVal= [[[self alloc] init] autorelease];
139         if(retVal!= NULL)
140         {
141             retVal->reachabilityRef = reachability;
142             retVal->localWiFiRef = NO;
143         }
144     }
145     return retVal;
146 }
147 
148 + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
149 {
150     SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
151     Reachability* retVal = NULL;
152     if(reachability!= NULL)
153     {
154         retVal= [[[self alloc] init] autorelease];
155         if(retVal!= NULL)
156         {
157             retVal->reachabilityRef = reachability;
158             retVal->localWiFiRef = NO;
159         }
160     }
161     return retVal;
162 }
163 
164 + (Reachability*) reachabilityForInternetConnection;
165 {
166     struct sockaddr_in zeroAddress;
167     bzero(&zeroAddress, sizeof(zeroAddress));
168     zeroAddress.sin_len = sizeof(zeroAddress);
169     zeroAddress.sin_family = AF_INET;
170     return [self reachabilityWithAddress: &zeroAddress];
171 }
172 
173 + (Reachability*) reachabilityForLocalWiFi;
174 {
175     struct sockaddr_in localWifiAddress;
176     bzero(&localWifiAddress, sizeof(localWifiAddress));
177     localWifiAddress.sin_len = sizeof(localWifiAddress);
178     localWifiAddress.sin_family = AF_INET;
179     // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
180     localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
181     Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress];
182     if(retVal!= NULL)
183     {
184         retVal->localWiFiRef = YES;
185     }
186     return retVal;
187 }
188 
189 #pragma mark Network Flag Handling
190 
191 - (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags
192 {
193     PrintReachabilityFlags(flags, "localWiFiStatusForFlags");
194     
195     BOOL retVal = NotReachable;
196     if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
197     {
198         retVal = ReachableViaWiFi;
199     }
200     return retVal;
201 }
202 
203 - (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags
204 {
205     PrintReachabilityFlags(flags, "networkStatusForFlags");
206     if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
207     {
208         // if target host is not reachable
209         return NotReachable;
210     }
211     
212     BOOL retVal = NotReachable;
213     
214     if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
215     {
216         // if target host is reachable and no connection is required
217         //  then we'll assume (for now) that your on Wi-Fi
218         retVal = ReachableViaWiFi;
219     }
220     
221     
222     if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
223          (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
224     {
225         // ... and the connection is on-demand (or on-traffic) if the
226         //     calling application is using the CFSocketStream or higher APIs
227         
228         if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
229         {
230             // ... and no [user] intervention is needed
231             retVal = ReachableViaWiFi;
232         }
233     }
234     
235     if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
236     {
237         // ... but WWAN connections are OK if the calling application
238         //     is using the CFNetwork (CFSocketStream?) APIs.
239         retVal = ReachableViaWWAN;
240     }
241     return retVal;
242 }
243 
244 - (BOOL) connectionRequired;
245 {
246     NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
247     SCNetworkReachabilityFlags flags;
248     if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
249     {
250         return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
251     }
252     return NO;
253 }
254 
255 - (NetworkStatus) currentReachabilityStatus
256 {
257     NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef");
258     NetworkStatus retVal = NotReachable;
259     SCNetworkReachabilityFlags flags;
260     if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
261     {
262         if(localWiFiRef)
263         {
264             retVal = [self localWiFiStatusForFlags: flags];
265         }
266         else
267         {
268             retVal = [self networkStatusForFlags: flags];
269         }
270     }
271     return retVal;
272 }
273 @end

简单使用方法

 1 +(BOOL) isNetWorkReachable
 2 {
 3     // define boolean value
 4     BOOL bRet;
 5     // check reachability to www.apple.com
 6     Reachability *r = [Reachability reachabilityWithHostName: @"www.apple.com"];
 7     // set boolean value according to current reachability status
 8     switch ([r currentReachabilityStatus]) {
 9         case NotReachable: // not reachable
10             bRet = NO;12             break;
13             
14         case ReachableViaWiFi: // reachable
15             bRet = YES;17             break;
18             
19         case ReachableViaWWAN: // reachable
20             bRet = YES;22             break;
23             
24         default: // unkown
25             bRet = NO;27             break;
28     }
29     // return boolean value
30     return bRet;
31 }