Reachability源代码

1.Reachability.h

#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>

typedef enum {
NotReachable = 0,
ReachableViaWiFi,
ReachableViaWWAN
} NetworkStatus;
#define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification"

@interface Reachability: NSObject
{
BOOL localWiFiRef;
SCNetworkReachabilityRef reachabilityRef;
}

//reachabilityWithHostName- Use to check the reachability of a particular host name.
+ (Reachability*) reachabilityWithHostName: (NSString*) hostName;

//reachabilityWithAddress- Use to check the reachability of a particular IP address.
+ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;

//reachabilityForInternetConnection- checks whether the default route is available. 
//  Should be used by applications that do not connect to a particular host
+ (Reachability*) reachabilityForInternetConnection;

//reachabilityForLocalWiFi- checks whether a local wifi connection is available.
+ (Reachability*) reachabilityForLocalWiFi;

//Start listening for reachability notifications on the current run loop
- (BOOL) startNotifier;
- (void) stopNotifier;

- (NetworkStatus) currentReachabilityStatus;
//WWAN may be available, but not active until a connection has been established.
//WiFi may require a connection for VPN on Demand.
- (BOOL) connectionRequired;
@end


======================================================================================================================

2.Reachability.m


#import <sys/socket.h>
#import <netinet/in.h>
#import <netinet6/in6.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>

#import <CoreFoundation/CoreFoundation.h>

#import "Reachability.h"

#define kShouldPrintReachabilityFlags 1

static void PrintReachabilityFlags(SCNetworkReachabilityFlags    flags, const char* comment)
{
#if kShouldPrintReachabilityFlags

    NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
   (flags & kSCNetworkReachabilityFlagsIsWWAN)      ? 'W' : '-',
   (flags & kSCNetworkReachabilityFlagsReachable)            ? 'R' : '-',
  
   (flags & kSCNetworkReachabilityFlagsTransientConnection)  ? 't' : '-',
   (flags & kSCNetworkReachabilityFlagsConnectionRequired)   ? 'c' : '-',
   (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic)  ? 'C' : '-',
   (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
   (flags & kSCNetworkReachabilityFlagsConnectionOnDemand)   ? 'D' : '-',
   (flags & kSCNetworkReachabilityFlagsIsLocalAddress)       ? 'l' : '-',
   (flags & kSCNetworkReachabilityFlagsIsDirect)             ? 'd' : '-',
   comment
   );
#endif
}


@implementation Reachability
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
{
#pragma unused (target, flags)
NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");

//We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively
// in case someon uses the Reachablity object in a different thread.
NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init];

Reachability* noteObject = (Reachability*) info;
// Post a notification to notify the client that the network reachability changed.
[[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];

[myPool release];
}

- (BOOL) startNotifier
{
BOOL retVal = NO;
SCNetworkReachabilityContext context = {0, self, NULL, NULL, NULL};
if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
{
  if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
  {
   retVal = YES;
  }
}
return retVal;
}

- (void) stopNotifier
{
if(reachabilityRef!= NULL)
{
  SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
}
}

- (void) dealloc
{
[self stopNotifier];
if(reachabilityRef!= NULL)
{
  CFRelease(reachabilityRef);
}
[super dealloc];
}

+ (Reachability*) reachabilityWithHostName: (NSString*) hostName;
{
Reachability* retVal = NULL;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
if(reachability!= NULL)
{
  retVal= [[[self alloc] init] autorelease];
  if(retVal!= NULL)
  {
   retVal->reachabilityRef = reachability;
   retVal->localWiFiRef = NO;
  }
}
return retVal;
}

+ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
{
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
Reachability* retVal = NULL;
if(reachability!= NULL)
{
  retVal= [[[self alloc] init] autorelease];
  if(retVal!= NULL)
  {
   retVal->reachabilityRef = reachability;
   retVal->localWiFiRef = NO;
  }
}
return retVal;
}

+ (Reachability*) reachabilityForInternetConnection;
{
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
return [self reachabilityWithAddress: &zeroAddress];
}

+ (Reachability*) reachabilityForLocalWiFi;
{
struct sockaddr_in localWifiAddress;
bzero(&localWifiAddress, sizeof(localWifiAddress));
localWifiAddress.sin_len = sizeof(localWifiAddress);
localWifiAddress.sin_family = AF_INET;
// IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress];
if(retVal!= NULL)
{
  retVal->localWiFiRef = YES;
}
return retVal;
}

#pragma mark Network Flag Handling

- (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags
{
PrintReachabilityFlags(flags, "localWiFiStatusForFlags");

BOOL retVal = NotReachable;
if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
{
  retVal = ReachableViaWiFi;
}
return retVal;
}

- (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags
{
PrintReachabilityFlags(flags, "networkStatusForFlags");
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
{
  // if target host is not reachable
  return NotReachable;
}

BOOL retVal = NotReachable;

if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
{
  // if target host is reachable and no connection is required
  //  then we'll assume (for now) that your on Wi-Fi
  retVal = ReachableViaWiFi;
}


if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
  (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
{
   // ... and the connection is on-demand (or on-traffic) if the
   //     calling application is using the CFSocketStream or higher APIs

   if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
   {
    // ... and no [user] intervention is needed
    retVal = ReachableViaWiFi;
   }
  }

if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
{
  // ... but WWAN connections are OK if the calling application
  //     is using the CFNetwork (CFSocketStream?) APIs.
  retVal = ReachableViaWWAN;
}
return retVal;
}

- (BOOL) connectionRequired;
{
NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
{
  return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
}
return NO;
}

- (NetworkStatus) currentReachabilityStatus
{
NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef");
NetworkStatus retVal = NotReachable;
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
{
  if(localWiFiRef)
  {
   retVal = [self localWiFiStatusForFlags: flags];
  }
  else
  {
   retVal = [self networkStatusForFlags: flags];
  }
}
return retVal;
}
@end

===============================================================================================================================

3.delegate.h

#import <UIKit/UIKit.h>

@class Reachability;
@interface ReachabilityAppDelegate: NSObject {
    IBOutlet UIWindow* window;
    IBOutlet UIView* contentView;
    IBOutlet UILabel* summaryLabel;

    IBOutlet UITextField* remoteHostLabel;
    IBOutlet UIImageView* remoteHostIcon;
    IBOutlet UITextField* remoteHostStatusField;
   
    IBOutlet UIImageView* internetConnectionIcon;
    IBOutlet UITextField* internetConnectionStatusField;
   
    IBOutlet UIImageView* localWiFiConnectionIcon;
    IBOutlet UITextField* localWiFiConnectionStatusField;
   
    Reachability* hostReach;
    Reachability* internetReach;
    Reachability* wifiReach;
}
@end

===========================================================================================================================

4.delegate.m


#import "ReachabilityAppDelegate.h"
#import "Reachability.h"

@implementation ReachabilityAppDelegate

- (void) configureTextField: (UITextField*) textField imageView: (UIImageView*) imageView reachability: (Reachability*) curReach
{
    NetworkStatus netStatus = [curReach currentReachabilityStatus];
    BOOL connectionRequired= [curReach connectionRequired];
    NSString* statusString= @"";
    switch (netStatus)
    {
        case NotReachable:
        {
            statusString = @"Access Not Available";
            imageView.image = [UIImage imageNamed: @"stop-32.png"] ;
            //Minor interface detail- connectionRequired may return yes, even when the host is unreachable.  We cover that up here...
            connectionRequired= NO; 
            break;
        }
           
        case ReachableViaWWAN:
        {
            statusString = @"Reachable WWAN";
            imageView.image = [UIImage imageNamed: @"WWAN5.png"];
            break;
        }
        case ReachableViaWiFi:
        {
             statusString= @"Reachable WiFi";
            imageView.image = [UIImage imageNamed: @"Airport.png"];
            break;
      }
    }
    if(connectionRequired)
    {
        statusString= [NSString stringWithFormat: @"%@, Connection Required", statusString];
    }
    textField.text= statusString;
}

- (void) updateInterfaceWithReachability: (Reachability*) curReach
{
    if(curReach == hostReach)
{
  [self configureTextField: remoteHostStatusField imageView: remoteHostIcon reachability: curReach];
        NetworkStatus netStatus = [curReach currentReachabilityStatus];
        BOOL connectionRequired= [curReach connectionRequired];

        summaryLabel.hidden = (netStatus != ReachableViaWWAN);
        NSString* baseLabel=  @"";
        if(connectionRequired)
        {
            baseLabel=  @"Cellular data network is available.\n  Internet traffic will be routed through it after a connection is established.";
        }
        else
        {
            baseLabel=  @"Cellular data network is active.\n  Internet traffic will be routed through it.";
        }
        summaryLabel.text= baseLabel;
    }
if(curReach == internetReach)
{
  [self configureTextField: internetConnectionStatusField imageView: internetConnectionIcon reachability: curReach];
}
if(curReach == wifiReach)
{
  [self configureTextField: localWiFiConnectionStatusField imageView: localWiFiConnectionIcon reachability: curReach];
}

}

//Called by Reachability whenever status changes.
- (void) reachabilityChanged: (NSNotification* )note
{
Reachability* curReach = [note object];
NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
[self updateInterfaceWithReachability: curReach];
}


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

    // Observe the kNetworkReachabilityChangedNotification. When that notification is posted, the
    // method "reachabilityChanged" will be called.
    [[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"];
hostReach = [[Reachability reachabilityWithHostName: @"www.apple.com"] retain];
[hostReach startNotifier];
[self updateInterfaceWithReachability: hostReach];

    internetReach = [[Reachability reachabilityForInternetConnection] retain];
[internetReach startNotifier];
[self updateInterfaceWithReachability: internetReach];

    wifiReach = [[Reachability reachabilityForLocalWiFi] retain];
[wifiReach startNotifier];
[self updateInterfaceWithReachability: wifiReach];

[window makeKeyAndVisible];
   
}
@end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值