zoukankan      html  css  js  c++  java
  • 09-获取指定Wi-Fi信息

    一、公共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
     

    对应的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);
    }
     
     
    }

    四、总结

  • 相关阅读:
    移动端点击事件300ms延迟问题解决方案——fastclick.js
    hover样式失效的解决方法
    phtoshop cs6 下载安装及破解方法(另附Photoshop CC 2018破解版图文教程)
    CCS3怎么实现border边框渐变效果
    使用git clone命令克隆github项目到本地时出错,提示没有权限的解决方法
    CSS3实现背景透明文字不透明
    (三十六)类数组对象arguments
    (三十五)函数的使用
    (三十四)设计模式之发布订阅模式
    (三十三)设计模式之混合模式
  • 原文地址:https://www.cnblogs.com/iyuanxiaojun/p/4472861.html
Copyright © 2011-2022 走看看