zoukankan      html  css  js  c++  java
  • 关于在iOS设备上探测WIFI,3G,GPRS使用情况的细节

    由于设计的游戏需要有一些联网请求,但有时候在设备未连接网络的情况下,如果对网络情况不加以判断,则可能造成游戏为了等游戏超时,浪费不必要的时间。

    所以在游戏启动时检测一下网络状况是很必要的,而且当玩家的设备连接上网络以后,有一个回调函数也是非常必要的一件事儿,这样可能更方便我们在后台下载数据库等信息。

    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
    ",
     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里面调用的部分

     1 - (void) applicationDidFinishLaunching: (UIApplication* )application 
     2 {
     3     #pragma unused(application)
     4     contentView.backgroundColor = [UIColor groupTableViewBackgroundColor];
     5     
     6     summaryLabel.hidden = YES;        
     7     
     8  
     9     //这句是设定一个回调函数reachability,当网络条件发生变化时则去调用reachabilityChanged
    10     [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(reachabilityChanged:) name: kReachabilityChangedNotification object: nil];
    11  
    12     //Change the host name here to change the server your monitoring
    13     remoteHostLabel.text = [NSString stringWithFormat: @"Remote Host: %@", @"www.apple.com"];
    14     //设定target地址,这里是www.apple.com
    15     hostReach = [[Reachability reachabilityWithHostName: @"www.apple.com"] retain];
    16     //启动网络条件检测
    17     [hostReach startNotifier];
    18     //更新UI的网络状态显示
    19     [self updateInterfaceWithReachability: hostReach];
    20     
    21     //探测是否能连上internet网
    22     internetReach = [[Reachability reachabilityForInternetConnection] retain];
    23     [internetReach startNotifier];
    24     [self updateInterfaceWithReachability: internetReach];
    25  
    26     //探测wifi是否开启
    27     wifiReach = [[Reachability reachabilityForLocalWiFi] retain];
    28     [wifiReach startNotifier];
    29     [self updateInterfaceWithReachability: wifiReach];
    30  
    31     [window makeKeyAndVisible];
    32     
    33 }
    34 
    35 
    36 
    37 
    38 //如需要查看网络状态,如下调用即可
    39 NetworkStatus netStatus = [curReach currentReachabilityStatus];
    40 netStatus有ReachableViaWWAN(蜂窝网络3G之类的),ReachableViaWiFi(wifi连接),NotReachable(无法连接)
  • 相关阅读:
    【Android
    【数据结构】之链表(C语言描述)
    【数据结构】之顺序表(C语言描述)
    【Android
    【Android
    【Android
    【Android
    【Android
    在线HTTP速度测试(响应时间测试)及浏览器兼容测试
    阿里云 腾讯云 服务器挂载数据盘
  • 原文地址:https://www.cnblogs.com/yingkong1987/p/3231301.html
Copyright © 2011-2022 走看看