你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> iOS開發中WiFi相關功能總結

iOS開發中WiFi相關功能總結

編輯:IOS開發基礎

1983664_907572.jpg

投稿文章,作者:Haley_Wong(簡書)

查漏補缺集是自己曾經做過相關的功能,但是重做相關功能或者重新看到相關功能的實現,感覺理解上更深刻。這一類的文章集中記錄在查漏補缺集。

iOS 開發中難免會遇到很多與網絡方面的判斷,這裡做個匯總,大多可能是與WiFi相關的。

1.Ping域名、Ping某IP

有時候可能會遇到ping 某個域名或者ip通不通,再做下一步操作。這裡的ping與傳統的做get或者post請求還是有很大區別的。比如我們連接了某個WiFi,測試ping www.baidu.com,如果能ping 通,基本可以斷定可以上網了,但是如果我們做了一個get 請求(url 是www.baidu.com),路由器可能重定向這個WiFi內的某網頁了,依然沒有錯誤返回,就會誤認為可以正常上網。

這裡有關於ping命令的詳細解釋:百度百科Ping

iOS中想要ping域名或者ip,蘋果提供了一個官方例子SimplePing

在例子中,有一個蘋果已經封裝過的類【SimplePing.h】和【SimplePing.m】

使用起來也相當的簡單:

首先創建一個Ping對象:

 SimplePing *pinger = [[SimplePing alloc] initWithHostName:self.hostName];
 self.pinger = pinger;
 pinger.delegate = self;
 pinger.addressStyle = SimplePingAddressStyleICMPv4;
 [pinger start];

然後在start成功的代理方法中,發送數據報文:

/**
 *  start成功,也就是准備工作做完後的回調
 */
- (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address
{
    // 發送測試報文數據
    [self.pinger sendPingWithData:nil];
}
- (void)simplePing:(SimplePing *)pinger didFailWithError:(NSError *)error
{
    NSLog(@"didFailWithError");
    [self.pinger stop];
}

其他幾個代理方法也非常簡單,就簡單記錄一下:

// 發送測試報文成功的回調方法
- (void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber
{
    NSLog(@"#%u sent", sequenceNumber);
}
//發送測試報文失敗的回調方法
- (void)simplePing:(SimplePing *)pinger didFailToSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber error:(NSError *)error
{
    NSLog(@"#%u send failed: %@", sequenceNumber, error);
}
// 接收到ping的地址所返回的數據報文回調方法
- (void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber
{
    NSLog(@"#%u received, size=%zu", sequenceNumber, packet.length);
}
- (void)simplePing:(SimplePing *)pinger didReceiveUnexpectedPacket:(NSData *)packet
{
    NSLog(@"#%s",__func__);
}

注意點:

iOS 中 ping失敗後(即發送測試報文成功後,一直沒後收到響應的報文),不會有任何回調方法告知我們。而一般ping 一次的結果也不太准確,ping 花費的時間也非常短,所以我們一般會ping多次,發送一次ping 測試報文0.5s後檢測一下這一次ping是否已經收到響應。0.5s後檢測時,如果已經收到響應,則可以ping 通;如果沒有收到響應,則視為超時。

做法也有很多種,可以用NSTimer或者 {- (void)performSelector: withObject:afterDelay:}

這裡有一個別人寫的工程:https://github.com/lovesunstar/STPingTest

727768-ff8ab7124905812e.jpg

PingTest效果圖

727768-6d4c781945dd1334.jpg

終端ping效果圖

2.獲取WiFi信息

以前物聯網剛火的時候,出現過很多一體式無線路由,所以App裡難免會遇到要判斷當前所連接的WiFi,以及獲取WiFi信息的功能。13年的時候查過一些關於WiFi的方法,後面漸漸都忘記了。慚愧!!!

需要添加SystemConfiguration.framework 並在當前類中添加代碼#import

//獲取WiFi 信息,返回的字典中包含了WiFi的名稱、路由器的Mac地址、還有一個Data(轉換成字符串打印出來是wifi名稱)
- (NSDictionary *)fetchSSIDInfo {
    NSArray *ifs = (__bridge_transfer NSArray *)CNCopySupportedInterfaces();
    if (!ifs) {
        return nil;
    }
    NSDictionary *info = nil;
    for (NSString *ifnam in ifs) {
        info = (__bridge_transfer NSDictionary *)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
        if (info && [info count]) { break; }
    }
    return info;
}
//打印出來的結果:
2016-05-12 15:28:51.674 SimplePing[18883:6790207] WIFI_INFO:{
    BSSID = "a4:2b:8c:c:7f:bd";
    SSID = bdmy06;
    SSIDDATA = ;
}

3.獲取WiFi名稱

有了上一步,獲取WiFi名稱就非常簡單了。

NSString *WiFiName = info[@"SSID"];
//打印結果:
2016-05-12 15:35:13.059 SimplePing[18887:6791418] bdmy06

完整的:

- (NSString *)fetchWiFiName {
    NSArray *ifs = (__bridge_transfer NSArray *)CNCopySupportedInterfaces();
    if (!ifs) {
        return nil;
    }
    NSString *WiFiName = nil;
    for (NSString *ifnam in ifs) {
        NSDictionary *info = (__bridge_transfer NSDictionary *)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
        if (info && [info count]) {
            // 這裡其實對應的有三個key:kCNNetworkInfoKeySSID、kCNNetworkInfoKeyBSSID、kCNNetworkInfoKeySSIDData,
            // 不過它們都是CFStringRef類型的
            WiFiName = [info objectForKey:(__bridge NSString *)kCNNetworkInfoKeySSID];
//            WiFiName = [info objectForKey:@"SSID"];
            break;
        }
    }
    return WiFiName;
}

4.獲取當前所連接WiFi的網關地址

例如自己家的路由器一般默認的網關地址是192.168.1.1,獲取的就是這個192.168.1.1。

為什麼不直接寫死呢?

因為一些商場或者有多個路由器的網關地址是不一樣的,比如之前有個公司的網關是192.168.89.1。

這裡有篇博客,這是地址

需要導入的庫:

#import #import #import

獲取網關的方法

- (NSString *)getGatewayIpForCurrentWiFi {
    NSString *address = @"error";
    struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;
    int success = 0;
    // retrieve the current interfaces - returns 0 on success
    success = getifaddrs(&interfaces);
    if (success == 0) {
        // Loop through linked list of interfaces
        temp_addr = interfaces;
        //*/
        while(temp_addr != NULL) {
        /*/
         int i=255;
         while((i--)>0)
         //*/
            if(temp_addr->ifa_addr->sa_family == AF_INET) {
                // Check if interface is en0 which is the wifi connection on the iPhone
                if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"])
                {
                    // Get NSString from C String //ifa_addr
                    //ifa->ifa_dstaddr is the broadcast address, which explains the "255's"
                    //                    address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)];
                    address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
                    //routerIP----192.168.1.255 廣播地址
                    NSLog(@"broadcast address--%@",[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)]);
                    //--192.168.1.106 本機地址
                    NSLog(@"local device ip--%@",[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)]);
                    //--255.255.255.0 子網掩碼地址
                    NSLog(@"netmask--%@",[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_netmask)->sin_addr)]);
                    //--en0 端口地址
                    NSLog(@"interface--%@",[NSString stringWithUTF8String:temp_addr->ifa_name]);
                }
            }
            temp_addr = temp_addr->ifa_next;
        }
    }
    // Free memory
    freeifaddrs(interfaces);
    in_addr_t i = inet_addr([address cStringUsingEncoding:NSUTF8StringEncoding]);
    in_addr_t* x = &i;
    unsigned char *s = getdefaultgateway(x);
    NSString *ip=[NSString stringWithFormat:@"%d.%d.%d.%d",s[0],s[1],s[2],s[3]];
    free(s);
    return ip;
}

其中 getdefaultgateway 是一個C語言文件中的方法,在工程裡可以找到。

5.獲取本機在WiFi環境下的IP地址

獲取本機在WiFi環境下的ip地址,在上一節中其實已經寫過,這裡將其提取出來即可:

- (NSString *)getLocalIPAddressForCurrentWiFi
{
    NSString *address = nil;
    struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;
    int success = 0;
    // retrieve the current interfaces - returns 0 on success
    success = getifaddrs(&interfaces);
    if (success == 0) {
        // Loop through linked list of interfaces
        temp_addr = interfaces;
        while(temp_addr != NULL) {
            if(temp_addr->ifa_addr->sa_family == AF_INET) {
                // Check if interface is en0 which is the wifi connection on the iPhone
                if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
                    address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
                    return address;
                }
            }
            temp_addr = temp_addr->ifa_next;
        }
        freeifaddrs(interfaces);
    }
    return nil;
}

同樣的方式也可以獲取廣播地址、子網掩碼、端口等,組裝成一個字典。

- (NSMutableDictionary *)getLocalInfoForCurrentWiFi {
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;
    int success = 0;
    // retrieve the current interfaces - returns 0 on success
    success = getifaddrs(&interfaces);
    if (success == 0) {
        // Loop through linked list of interfaces
        temp_addr = interfaces;
        //*/
        while(temp_addr != NULL) {
            if(temp_addr->ifa_addr->sa_family == AF_INET) {
                // Check if interface is en0 which is the wifi connection on the iPhone
                if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
                    //----192.168.1.255 廣播地址
                    NSString *broadcast = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)];
                    if (broadcast) {
                        [dict setObject:broadcast forKey:@"broadcast"];
                    }
                    NSLog(@"broadcast address--%@",broadcast);
                    //--192.168.1.106 本機地址
                    NSString *localIp = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
                    if (localIp) {
                        [dict setObject:localIp forKey:@"localIp"];
                    }
                    NSLog(@"local device ip--%@",localIp);
                    //--255.255.255.0 子網掩碼地址
                    NSString *netmask = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_netmask)->sin_addr)];
                    if (netmask) {
                        [dict setObject:netmask forKey:@"netmask"];
                    }
                    NSLog(@"netmask--%@",netmask);
                    //--en0 端口地址
                    NSString *interface = [NSString stringWithUTF8String:temp_addr->ifa_name];
                    if (interface) {
                        [dict setObject:interface forKey:@"interface"];
                    }
                    NSLog(@"interface--%@",interface);
                    return dict;
                }
            }
            temp_addr = temp_addr->ifa_next;
        }
    }
    // Free memory
    freeifaddrs(interfaces);
    return dict;
}

將返回的字典打印出來:

2016-05-12 17:59:09.257 SimplePing[19141:6830567] wifi:{
    broadcast = "192.168.1.255";
    interface = en0;
    localIp = "192.168.1.7";
    netmask = "255.255.255.0";
}
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved