检查网络状态

检查网络状态   

最近在做 iphone网络链接部分,于是鄙人将各路的好贴整合了一下并且加了自己的一些想法,希望对大家有所帮助~~ 写的不好的地方还请各位大大多多指教啊

iPhone SDK中附带了 SCNetworkReachabilityCre ateWithAddress用于检查ip地址是否可以访问。传入清零地址(0.0.0.0)可用来查询网络状态。
网络可 使用时返回YES,否则为NO。

返回标记:
kSCNetworkReachabilityFl agsIsWWAN        :测试用户使用的时运营商的网络还是本地wifi。
kSCNetworkFlagsConnectio nRequired:无需更多链接。
kSCNetworkFlagsReachable :表明网络可以访问。


代码如下:

头文件:
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#import <netdb.h>
#import <SystemConfiguration/SCNetworkReachability.h>


frameworks:/System/Library/Frameworks/SystemConfiguration.framework


- (BOOL) connectedToNetwork
{
        // Create zero addy
        struct sockaddr_in zeroAddress;
        bzero(&zeroAddress, sizeof(zeroAddress));
        zeroAddress.sin_len = sizeof(zeroAddress);
        zeroAddress.sin_family = AF_INET;

        // Recover reachability flags
        SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCre ateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
        SCNetworkReachabilityFla gs flags;

        BOOL didRetrieveFlags = SCNetworkReachabilityGet Flags(defaultRouteReachability , &flags);
        CFRelease(defaultRouteReachability );

        if (!didRetrieveFlags)
        {
                return NO;
        }

        BOOL isReachable = flags & kSCNetworkFlagsReachable ;
        BOOL needsConnection = flags & kSCNetworkFlagsConnectio nRequired;
        return (isReachable && !needsConnection) ? YES : NO;
}

//call like:
-(void) start {
        if (![self connectedToNetwork]) {
                                UIAlertView *alert = [[UIAlertView alloc]
                                                initWithTitle:@"Network Connection Error"
                                                message:@"You need to be connected to the internet to use this feature."
                                                delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
                [alert show];
                [alert release];
                } else {
                        //do something
                }
}

使用上述方法可能会出现以下问题:

当使用者在使用你的应用程式的时候,如果关掉萤幕,将装置放在锁定状态(就是那个重新 打开时 需要在萤幕上画一下「解锁」的状态)一阵子,然后再按一下按钮恢复使用,这个时候你想要做一些网路操作,其实是可以连线,但是Reachability API 还是告诉你无法连线;或刚打开应用程式的时候,也告诉你无法连线。当你需要判断能不能连线,使用者用了哪种连线而应不应该继续连线的时候,其实使用者可以 连线,API 却始终一直告诉你不能连线。

把装置设定为锁定,然后恢复使用的状况是这样的-苹果的设计是,为了节省电力消耗,会在进入锁定状态后,自动关闭无线网路介面,而当你解除锁定后,才会把无线网路再度打开。 而Reachability 基本上只询问「目前的网路状态」,如果装置的无线网路正处于从关闭的状态恢复的阶段,这时后回传的结果便是无法连线。

顺道一提,在第三方应用程式中,可以在Info.plist 档案中,设定UIRequiresPersistentWifi 这个选项,文件中说这个设定可以让应用程式持续保持无线网路的连线状态,但是,就算设了这 项设定,在进入锁定状态后,系统仍然会自动关闭无线网路介面,这项设定仅局限于iPhone 一直开着、你不去把萤幕关掉的状况。

至于怎样在锁定状态下继续保持连线,那又是另外一个话题了。

刚进入应用程式的时候,也往往回传无法连线-猜测应该是使用iPhone 主画面(Springboard)的时候,无线网路介面大概也是关闭的。 在点选要用什么应用程式的时候,好像也用不到什么网路功能,为了节电把网路介面关了也好。 至于定时检查信箱、或从AppStore 下载软体什么的,应该是苹果有其他自己的背景程序,负责呼叫网路介面。

简言之,就是你常会遇到「问的时候说没有,但是下一秒钟网路就通」的状况,遇到这种状况,要使用比较白烂的作法,可以向Reachability 连续问两次 ,如果第一次说没有第二次却说有,那就代表其实还是有网路…可能比较好的作法,可以是,我们不要叫一个method 直接回传给我们网路状态,而是变成delegate 的方式来处理。

流程大概是这样,这边稍微有些啰嗦-

      1. 设计两个delegate method,分别用于有网路与没网路两种状况。
   
2. 先生出一个SCNetworkReachabilityRef 物件,然后用SCNetworkReachabilityGet Flags() 抓取目前的网路状态,如果是有,就呼叫「有网路」的那组delegate method,直接结束。
      3. 如果这一次抓取网路状态的结果是没有连线,我们就对刚刚产生的SCNetworkReachabilityRef 物件设定一个SCNetworkReachabilityCallBack function。 因为只要连线状态出现变化,就会呼叫这个function,所以,在呼叫到的时候,再用SCNetworkReachabilityGetFlags() 抓一次目前的网路状态,决定要回传是「有网路」或「没网路」的delegate method。 如果有呼叫到,通常是会有,如此一来,我们可以捕捉到了「第一次说没有,但是后来又有网路」的状况,并且成功回传「有网路」。
   
4. 同时设一组timer(或用NSObject 的perform selector after delay 之类的),如果超过一段时间,SCNetworkReachability API 都没有被呼叫前一点中提到的SCNetworkReachabilityCallBack function,就代表不但一开始没网路, 而且后来一直还是那个状态,那…就代表一直没网路。这时后呼叫「没网路」的delegate method。
      5. 记得要release 那个SCNetworkReachabilityRef 物件…。

采用这种实作,在没有网路连线的状态下,就会需要几秒钟的等待,确定目前的确没有网路连线。 不过嘛,反正没有网路连线,也不能够做什么别的事情,所以等个几秒钟也无所谓嘛。

顺道一提,iPhone SDK 关于SCNetworkReachability 的说明文件里头有个 错误,在讲如何设定SCNetworkReachabilityCal lBack 的部份提到-

        Here is an example of a function declared to conform to this type:

    
- (void)MyReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值