zoukankan      html  css  js  c++  java
  • 使用 Reachability 获取网络状态

    Reachability

    source https://developer.apple.com/library/ios/samplecode/Reachability/Introduction/Intro.html

    reachability 为苹果官方demo提供的一个检测网络状态的代码,下载源码后本人对其进行了修改,修改后源码:

    reachability.h  +  reachability.m

    #import <Foundation/Foundation.h>
    #import <SystemConfiguration/SystemConfiguration.h>
    #import <netinet/in.h>
    
    
    typedef enum : NSInteger {
        NotReachable = 0,
        ReachableViaWiFi,
        ReachableViaWWAN
    } NetworkStatus;
    
    
    extern NSString *kReachabilityChangedNotification;
    
    
    @interface Reachability : NSObject
    
    /*!
     * Use to check the reachability of a given host name.
     */
    + (instancetype)reachabilityWithHostName:(NSString *)hostName;
    
    /*!
     * Use to check the reachability of a given IP address.
     */
    + (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;
    
    /*!
     * Checks whether the default route is available. Should be used by applications that do not connect to a particular host.
     */
    + (instancetype)reachabilityForInternetConnection;
    
    /*!
     * Checks whether a local WiFi connection is available.
     */
    + (instancetype)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;
    
    /*!
     *  测试是否能连接网
     */
    + (NetworkStatus)isExistNetwork;
    
    @end
    #import <arpa/inet.h>
    #import <ifaddrs.h>
    #import <netdb.h>
    #import <sys/socket.h>
    
    #import <CoreFoundation/CoreFoundation.h>
    
    #import "Reachability.h"
    
    
    NSString *kReachabilityChangedNotification = @"kNetworkReachabilityChangedNotification";
    
    
    #pragma mark - Supporting functions
    
    #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
    ",
              (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
    }
    
    
    static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
    {
    #pragma unused (target, flags)
        NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
        NSCAssert([(__bridge NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
    
        Reachability* noteObject = (__bridge Reachability *)info;
        // Post a notification to notify the client that the network reachability changed.
        [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
    }
    
    
    #pragma mark - Reachability implementation
    
    @implementation Reachability
    {
        BOOL _alwaysReturnLocalWiFiStatus; //default is NO
        SCNetworkReachabilityRef _reachabilityRef;
    }
    
    + (instancetype)reachabilityWithHostName:(NSString *)hostName
    {
        Reachability* returnValue = NULL;
        SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
        if (reachability != NULL)
        {
            returnValue= [[self alloc] init];
            if (returnValue != NULL)
            {
                returnValue->_reachabilityRef = reachability;
                returnValue->_alwaysReturnLocalWiFiStatus = NO;
            }
        }
        return returnValue;
    }
    
    
    + (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress
    {
        SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress);
    
        Reachability* returnValue = NULL;
    
        if (reachability != NULL)
        {
            returnValue = [[self alloc] init];
            if (returnValue != NULL)
            {
                returnValue->_reachabilityRef = reachability;
                returnValue->_alwaysReturnLocalWiFiStatus = NO;
            }
        }
        return returnValue;
    }
    
    
    
    + (instancetype)reachabilityForInternetConnection
    {
        struct sockaddr_in zeroAddress;
        bzero(&zeroAddress, sizeof(zeroAddress));
        zeroAddress.sin_len = sizeof(zeroAddress);
        zeroAddress.sin_family = AF_INET;
        
        return [self reachabilityWithAddress:&zeroAddress];
    }
    
    
    + (instancetype)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* returnValue = [self reachabilityWithAddress: &localWifiAddress];
        if (returnValue != NULL)
        {
            returnValue->_alwaysReturnLocalWiFiStatus = YES;
        }
        
        return returnValue;
    }
    
    
    #pragma mark - Start and stop notifier
    
    - (BOOL)startNotifier
    {
        BOOL returnValue = NO;
        SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
    
        if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context))
        {
            if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
            {
                returnValue = YES;
            }
        }
        
        return returnValue;
    }
    
    
    - (void)stopNotifier
    {
        if (_reachabilityRef != NULL)
        {
            SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
        }
    }
    
    
    - (void)dealloc
    {
        [self stopNotifier];
        if (_reachabilityRef != NULL)
        {
            CFRelease(_reachabilityRef);
        }
    }
    
    
    #pragma mark - Network Flag Handling
    
    - (NetworkStatus)localWiFiStatusForFlags:(SCNetworkReachabilityFlags)flags
    {
        PrintReachabilityFlags(flags, "localWiFiStatusForFlags");
        NetworkStatus returnValue = NotReachable;
    
        if ((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
        {
            returnValue = ReachableViaWiFi;
        }
        
        return returnValue;
    }
    
    
    - (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags
    {
        PrintReachabilityFlags(flags, "networkStatusForFlags");
        if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
        {
            // The target host is not reachable.
            return NotReachable;
        }
    
        NetworkStatus returnValue = NotReachable;
    
        if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
        {
            /*
             If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi...
             */
            returnValue = 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...
                 */
                returnValue = ReachableViaWiFi;
            }
        }
    
        if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
        {
            /*
             ... but WWAN connections are OK if the calling application is using the CFNetwork APIs.
             */
            returnValue = ReachableViaWWAN;
        }
        
        return returnValue;
    }
    
    
    - (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 SCNetworkReachabilityRef");
        NetworkStatus returnValue = NotReachable;
        SCNetworkReachabilityFlags flags;
        
        if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
        {
            if (_alwaysReturnLocalWiFiStatus)
            {
                returnValue = [self localWiFiStatusForFlags:flags];
            }
            else
            {
                returnValue = [self networkStatusForFlags:flags];
            }
        }
        
        return returnValue;
    }
    
    
    + (NetworkStatus)isExistNetwork
    {
        NetworkStatus isExistenceNetwork;
        
        //单例
        static Reachability *reachability = nil;
        
        //服务器地址选择了百度
        if (reachability == nil)
        {
            reachability = [Reachability reachabilityWithHostName:@"www.baidu.com"];
        }
        
        switch([reachability currentReachabilityStatus]) {
            case NotReachable:
                isExistenceNetwork = NotReachable;
                break;
            case ReachableViaWWAN:
                isExistenceNetwork = ReachableViaWWAN;
                break;
            case ReachableViaWiFi:
                isExistenceNetwork = ReachableViaWiFi;
                break;
        }
        
        return  isExistenceNetwork;
    }
    
    @end

    直接使用下面的代码来得到网络信息,是单例模式,无需担心浪费内存

        [Reachability isExistNetwork];

    其返回3个枚举值,判断一下即可,

        NotReachable, ReachableViaWiFi, ReachableViaWWAN

    使用通知来监听网络状态

    1.定义属性(strong)

    @property (nonatomic, strong) Reachability *hostReachability;
    @property (nonatomic, strong) Reachability *internetReachability;
    @property (nonatomic, strong) Reachability *wifiReachability;

    2.指定监听的方法

    - (void) reachabilityChanged:(NSNotification *)note
    {
        Reachability *tmp = [note object];
        
        NSLog(@"%d", [tmp currentReachabilityStatus]);
    }

    3.初始化以及监听

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(reachabilityChanged:)
                                                     name:kReachabilityChangedNotification
                                                   object:nil];
        
        NSString *remoteHostName = @"www.baidu.com";
        _hostReachability = [Reachability reachabilityWithHostName:remoteHostName];
        [_hostReachability startNotifier];
        
        _internetReachability = [Reachability reachabilityForInternetConnection];
        [_internetReachability startNotifier];
        
        _wifiReachability = [Reachability reachabilityForLocalWiFi];
        [_wifiReachability startNotifier];

  • 相关阅读:
    【MySQL】MySQL环境搭建
    【Linux】 工作中遇到并使用的命令
    k8s入门系列之guestbook快速部署
    k8s入门系列之扩展组件(二)kube-ui安装篇
    k8s入门系列之扩展组件(一)DNS安装篇
    k8s入门系列之集群安装篇
    爬虫抓取百度贴吧帖子内容
    爬虫抓取糗事百科的段子
    kibana使用操作部分
    elk实战分析nginx日志文档
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3607701.html
Copyright © 2011-2022 走看看