【问题标题】:iPad: How to get Ethernet IP address programmaticallyiPad:如何以编程方式获取以太网 IP 地址
【发布时间】:2016-07-12 20:50:54
【问题描述】:

我知道如何通过 en0 接口获取 IP 地址,如下所示: iPhone/iPad/OSX: How to get my IP address programmatically?

但现在我正在使用 Lightning 到 USB 3 相机适配器实现与 LAN 的以太网连接,以便在 9.3 中连接到没有 Wifi 的互联网,因此上述解决方案无法在没有无线连接的情况下解析 IP 地址. iPad 可以上网,现在重要的是应用程序可以解析设备自己的 IP 地址。

如何通过 Lightning->USB->Ethernet 连接获取 iPad 的 IP 地址?与无线相反。
提前致谢!

【问题讨论】:

    标签: ios objective-c ipad network-programming


    【解决方案1】:

    en2 接口。

    添加:

    [[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en2"]
    

    到第一个解决方案 iPhone/iPad/OSX: How to get my IP address programmatically?也可以通过有线连接获取设备的IP地址。

    更新:只是扩展上面链接的@Raptor 的解决方案;如果两者都存在,这将返回有线和无线 IP 地址。然后只需检查返回字典的值的长度,看看你正在使用什么。

    #import <ifaddrs.h>
    #import <arpa/inet.h>
    
    + (NSDictionary *)getBothIPAddresses {
        const NSString *WIFI_IF = @"en0";
        NSArray *KNOWN_WIRED_IFS = @[@"en1",@"en2",@"en3",@"en4"];
        NSArray *KNOWN_CELL_IFS = @[@"pdp_ip0",@"pdp_ip1",@"pdp_ip2",@"pdp_ip3"];
    
        const NSString *UNKNOWN_IP_ADDRESS = @"";
    
        NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithDictionary:@{@"wireless":UNKNOWN_IP_ADDRESS,
                                                                                            @"wired":UNKNOWN_IP_ADDRESS,
                                                                                             @"cell":UNKNOWN_IP_ADDRESS}];
    
        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 == NULL) {
                     temp_addr = temp_addr->ifa_next;
                     continue;
                }
                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:WIFI_IF]) {
                        // Get NSString from C String
                        [addresses setObject:[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)] forKey:@"wireless"];
                    
                    }
                    // Check if interface is a wired connection
                    if([KNOWN_WIRED_IFS containsObject:[NSString stringWithUTF8String:temp_addr->ifa_name]]) {
                        [addresses setObject:[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)] forKey:@"wired"];
                    }
                    // Check if interface is a cellular connection
                    if([KNOWN_CELL_IFS containsObject:[NSString stringWithUTF8String:temp_addr->ifa_name]]) {
                        [addresses setObject:[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)] forKey:@"cell"];
                    }
                }
    
                temp_addr = temp_addr->ifa_next;
            }
        }
        // Free memory
        freeifaddrs(interfaces);
    
        return addresses;
    }
    

    更新: en3接口,另一种可能;似乎取决于适配器的类型。让我觉得根据所使用的硬件可能还有更多我仍然缺少的接口,所以如果有人发现更多,请发表评论。

    更新: en4 也是;不一定像我最初想的那样依赖于适配器,因为具有所有相同硬件的 Mini 决定从一个接口切换到这个新接口。另外,我开始认为将 ifa_name 与格式为en[2..n] 的任何字符串进行比较可能会更容易,只要它在AF_INET 系列中(例如,en1 不是并且没有' t 返回我们正在寻找的地址);在没有更多证据的情况下为 Prod 实现类似的东西可能还为时过早,所以现在我使用“已知”有线接口列表进行管理。

    更新: 也考虑蜂窝AF_INET 接口,在What exactly means iOS networking interface name? what's pdp_ip ? what's ap? 中提到

    更新: 以太网 IP 地址最近开始出现在某些新 iPad 上的en1 接口上,因此当它是AF_INET 系列的成员时也应该考虑它。没有明显的韵律或原因,它发生在不同的 iPad 型号和 iOS 版本上。

    【讨论】:

    • 我已经让这段代码工作了,但是我注意到当 iPad 用 USB 电缆(不是以太网适配器)连接时,会出现一个带有 IP 地址的“en2”接口,但是我得到了一个如果我尝试在此接口上打开套接字,则会出现“没有到主机的路由”错误。除了尝试通过它们建立连接之外,还有什么方法可以检测和过滤这些接口?
    【解决方案2】:

    为 Swift 3 更新

     import arpa
        import ifaddrs
        
        class func getBothIPAddresses() -> [AnyHashable: Any] {
            let WIFI_IF: String = "en0"
            let KNOWN_WIRED_IFS: [Any] = ["en2", "en3", "en4"]
            let KNOWN_CELL_IFS: [Any] = ["pdp_ip0", "pdp_ip1", "pdp_ip2", "pdp_ip3"]
            let UNKNOWN_IP_ADDRESS: String = ""
            var addresses: [AnyHashable: Any] = ["wireless": UNKNOWN_IP_ADDRESS, "wired": UNKNOWN_IP_ADDRESS, "cell": UNKNOWN_IP_ADDRESS]
        
            var interfaces: ifaddrs? = nil
        
            var temp_addr: ifaddrs? = nil
            var success: Int = 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 != nil {
                    if temp_addr?.ifa_addr == nil {
                        temp_addr = temp_addr?.ifa_next
                        continue
                    }
                    if temp_addr?.ifa_addr?.sa_family == AF_INET {
                        // Check if interface is en0 which is the wifi connection on the iPhone
                        if (String(utf8String: temp_addr?.ifa_name) == WIFI_IF) {
                            // Get NSString from C String
                            addresses["wireless"] = String(utf8String: inet_ntoa((temp_addr?.ifa_addr as? sockaddr_in)?.sin_addr))
                        }
                        // Check if interface is a wired connection
                        if KNOWN_WIRED_IFS.contains(String(utf8String: temp_addr?.ifa_name)) {
                            addresses["wired"] = String(utf8String: inet_ntoa((temp_addr?.ifa_addr as? sockaddr_in)?.sin_addr))
                        }
                        // Check if interface is a cellular connection
                        if KNOWN_CELL_IFS.contains(String(utf8String: temp_addr?.ifa_name)) {
                            addresses["cell"] = String(utf8String: inet_ntoa((temp_addr?.ifa_addr as? sockaddr_in)?.sin_addr))
                        }
                    }
                    temp_addr = temp_addr?.ifa_next
                }
            }
                // Free memory
            freeifaddrs(interfaces)
            return addresses
        }
    

    【讨论】:

    • 我得到了这样的模块 arpa
    猜你喜欢
    • 1970-01-01
    • 2018-05-28
    • 1970-01-01
    • 1970-01-01
    • 2010-09-14
    • 1970-01-01
    • 2023-03-27
    • 2022-10-12
    相关资源
    最近更新 更多