你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> iOS客戶端公共WIFI解決方案

iOS客戶端公共WIFI解決方案

編輯:IOS開發基礎

一、公共WIFI綜述

現在很多公司都在做免費WIFI,車站、公交、地鐵、餐廳,只要是人員密集流動的地方就有WIFI,免費WIFI從最初的網頁認證方式也逐漸向客戶端認證方式偏移。本文主要討論iOS認證上網的解決方案。

iOS端WIFI應用的相關開發,主要存在以下問題:

  1. iOS系統WIFI相關的接口很少,大部分接口都是私有接口

  2. 在設備連接上WIFI,沒有通過路由器認證前,如果關閉iOS自動彈出的Portal頁面,iPhone的WIFI會自動斷開

  3. 如何禁止iOS系統自動彈Portal頁面

  4. 公共WIFI的名稱確定及不確定時的處理辦法

本文主要討論在使用公開的API,即可以提交到App Store的應用。

二、基礎信息獲取

1. 獲取網卡IP

+ (NSString *)localIPAddress
{
    NSString *localIP = nil;
    struct ifaddrs *addrs;
    if (getifaddrs(&addrs)==0) {
        const struct ifaddrs *cursor = addrs;
        while (cursor != NULL) {
            if (cursor->ifa_addr->sa_family == AF_INET && (cursor->ifa_flags & IFF_LOOPBACK) == 0)
            {
                NSString *name = [NSString stringWithUTF8String:cursor->ifa_name];
                if ([name isEqualToString:@"en0"]) // Wi-Fi adapter
                {
                    localIP = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)cursor->ifa_addr)->sin_addr)];
                    break;
                }
            }
            cursor = cursor->ifa_next;
        }
        freeifaddrs(addrs);
    }
    return localIP;
}

2. 獲取網卡信息

- (NSDictionary *)getWIFIDic
{
    CFArrayRef myArray = CNCopySupportedInterfaces();
    if (myArray != nil) {
        CFDictionaryRef myDict = CNCopyCurrentNetworkInfo(CFArrayGetValueAtIndex(myArray, 0));
        if (myDict != nil) {
            NSDictionary *dic = (NSDictionary*)CFBridgingRelease(myDict);
            return dic;
        }
    }
    return nil;
}

- (NSString *)getBSSID
{
    NSDictionary *dic = [self getWIFIDic];
    if (dic == nil) {
        return nil;
    }
    return dic[@"BSSID"];
}

- (NSString *)getSSID
{
    NSDictionary *dic = [self getWIFIDic];
    if (dic == nil) {
        return nil;
    }
    return dic[@"SSID"];
}

**注意事項**

在實際測試時,獲取網卡信息**getWIFIDic**方法,在部分路由器上耗時很長(10秒以上),如果直接放在主線程中,會導致界面卡死。在認證相關的應用中,會根據網卡上的BSSID(例如:以特定3d:e6:c3開頭的即為本公司架設網絡)來判斷是否屬於本公司的路由。SSID、BSSID若為應用啟動時必須獲取的信息(我們公司的應用,就是這種),這個時候怎樣處理呢?

放在異步線程,獲取到網卡信息再初使化界面,這種方法依然會導致在某些路由器下初次打開界面超長時間的等待,我們的處理方法是,如果3秒內能夠獲取到相應的配置信息,直接根據配置信息初使化界面,在超過3秒時,給予默認的假WIFI信息,初使化界面。異步線程獲取到真實的配置信息後,再重新更新界面。

三、認證過程中的棘手問題

1. Portal禁止彈出與WIFI自動關閉的問題

正常情況,用戶使用iPhone手機連接帶有Portal認證的路由器,在連接成功後,iOS系統會在已有列表中隨機選擇連接指定的網址(例如:www.itools.info)以測試當前路由器是否需要Portal認證。在需要Portal認證的網絡,系統會彈出Portal頁面,這個時候,如果用關掉portal頁面,或者直接切換到其它應用,WIFI網絡會直接自動斷開(根本不給客戶端認證機會^_^)。

我們的解決辦法是路由器白名單,讓路由器放行所有Portal測試的IP,以下為測試的域名:

www.appleiphonecell.com
captive.apple.com
www.itools.info
www.ibook.info
www.airport.us
www.thinkdifferent.us

對應的IP地址:

23.207.103.91
23.33.54.18
23.44.167.91
23.67.183.91
96.7.103.91
23.42.71.91
23.34.105.211
23.59.167.91
23.42.184.50
23.47.232.190
23.77.23.91
23.194.87.91
23.61.91.190
23.218.12.50
23.2.38.95
23.46.135.91
172.225.213.179
218.205.66.94
23.64.251.249
23.58.250.189

將以上所有IP加到路由器的白名單中,即可解決iPhone斷開WIFI的問題,但是同時也不自動彈出Portal頁面了,用戶打開浏覽器才會重定向到Portal頁面。

2. WIFI名確定解決方法

如果公司部署的公共WIFI名確定的情況,就比較簡單了,不需要配置上述白名單也可以保證WIFI不斷開,具體辦法是,在程序啟動時,向iOS系統注冊SSID,方法如下:

- (void)registerNetwork:(NSString *)ssid
{
    NSString *values[] = {ssid};
    CFArrayRef arrayRef = CFArrayCreate(kCFAllocatorDefault,(void *)values,
                                        (CFIndex)1, &kCFTypeArrayCallBacks);
    if( CNSetSupportedSSIDs(arrayRef)) {
        NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
        CNMarkPortalOnline((__bridge CFStringRef)(ifs[0]));
        NSLog(@"%@", ifs);
    }


}

四、總結

蘋果對於WIFI這塊公開的API非常少,在開發公共WIFI應用時會遇到各種問題,上面是在使用非私有API的一些解決方案,如果大家有更優的辦法,歡迎留言分享。如果公司有企業賬號可以通過調用私有API的辦法來處理大部分需求。

原文地址:一葉博客

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved