【问题标题】:How to get the public IP address of the device如何获取设备的公网IP地址
【发布时间】:2015-02-26 19:42:12
【问题描述】:

我找到了this sample code 来获取所有本地 IP 地址,但我没有找到一个简单的解决方案来获取公共 IP。

来自 Apple 的 legacy class 允许这样做 ...但它是遗产...

【问题讨论】:

    标签: ios objective-c ip-address public


    【解决方案1】:

    就这么简单:

    NSString *publicIP = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"https://icanhazip.com/"] encoding:NSUTF8StringEncoding error:nil];
    publicIP = [publicIP stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]]; // IP comes with a newline for some reason
    

    【讨论】:

    • 它有效,这是获取IP地址的简短方法!谢谢
    • 哈哈哈。我不知道我对域名icanhazip.com 的网站的寿命有多信任。 :)
    • icanhazip.com 实际上是 Backspace 员工的一项非常知名的服务,并且已经运行多年(至少 7 年)。欲了解更多信息,请查看此链接:icanhazip FAQ
    • 在 Swift 中我回答了 here
    【解决方案2】:

    我过去使用过ALSystemUtilities。您基本上必须从外部拨打电话才能找到这一点。

    + (NSString *)externalIPAddress {
        // Check if we have an internet connection then try to get the External IP Address
        if (![self connectedViaWiFi] && ![self connectedVia3G]) {
            // Not connected to anything, return nil
            return nil;
        }
    
        // Get the external IP Address based on dynsns.org
        NSError *error = nil;
        NSString *theIpHtml = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.dyndns.org/cgi-bin/check_ip.cgi"]
                                                       encoding:NSUTF8StringEncoding
                                                          error:&error];
        if (!error) {
            NSUInteger  an_Integer;
            NSArray *ipItemsArray;
            NSString *externalIP;
            NSScanner *theScanner;
            NSString *text = nil;
    
            theScanner = [NSScanner scannerWithString:theIpHtml];
    
            while ([theScanner isAtEnd] == NO) {
    
                // find start of tag
                [theScanner scanUpToString:@"<" intoString:NULL] ;
    
                // find end of tag
                [theScanner scanUpToString:@">" intoString:&text] ;
    
                // replace the found tag with a space
                //(you can filter multi-spaces out later if you wish)
                theIpHtml = [theIpHtml stringByReplacingOccurrencesOfString:
                             [ NSString stringWithFormat:@"%@>", text]
                                                                 withString:@" "] ;
                ipItemsArray = [theIpHtml  componentsSeparatedByString:@" "];
                an_Integer = [ipItemsArray indexOfObject:@"Address:"];
                externalIP =[ipItemsArray objectAtIndex:++an_Integer];
            }
            // Check that you get something back
            if (externalIP == nil || externalIP.length <= 0) {
                // Error, no address found
                return nil;
            }
            // Return External IP
            return externalIP;
        } else {
            // Error, no address found
            return nil;
        }
    }
    

    来源ALSystemUtilities

    【讨论】:

    • 不打电话找不到吗?
    • 如果“公共 IP”是指“互联网将我视为来自的 IP 地址”,那么如果不询问互联网的某些部分,就不可能知道这一点。您的设备上没有发生 NAT;它发生在网络上。请注意,不同的设备可能会将您视为具有不同的 IP,具体取决于您如何路由到它们(包括某些设备可能会认为您具有 IPv4 地址而其他设备可能会认为您具有 IPv6 地址)。 “互联网”只是一个特定的网络;您可以使用不同的 IP 映射在许多不同的网络之间进行路由。
    【解决方案3】:

    感谢@Tarek 的回答

    这里是 Swift 4 版本的代码

    func getPublicIPAddress() -> String {
        var publicIP = ""
        do {
            try publicIP = String(contentsOf: URL(string: "https://www.bluewindsolution.com/tools/getpublicip.php")!, encoding: String.Encoding.utf8)
            publicIP = publicIP.trimmingCharacters(in: CharacterSet.whitespaces)
        }
        catch {
            print("Error: \(error)")
        }
        return publicIP
    }
    

    注意1:要获得公共IP地址,我们必须有外部站点才能返回公共IP。我使用的网站是商业公司网站,所以,直到业务消失为止。 p>

    注意2:您可以自己制作一些站点,但是Apple需要HTTPS站点才能使用此功能。

    【讨论】:

    • 关于您的 NOTE2,Apple 尚未强制使用 HTTPS,因此它们可以是 HTTP 网站。
    【解决方案4】:

    如果您想异步检索 IP,有一种方法可以在 1 行代码中使用 ipify.org 和 Alamofire:

    Alamofire.request("https://api.ipify.org").responseString { (response) in
        print(response.result.value ?? "Unable to get IP")
    }
    

    【讨论】:

      【解决方案5】:

      对于我们这些使用 Swift 的人,这是我对 Andrei 答案的翻译,并添加了 NSURLSession 以在后台运行它。要检查网络,我使用Reachability.swift。另外,请记住将 dyndns.org 添加到 NSExceptionDomains 以获取 NSAppTransportSecurity 在您的 info.plist 中。

      var ipAddress:String?
      func getIPAddress() {
      
          if reachability!.isReachable() == false {
              return
          }
      
          guard let ipServiceURL = NSURL(string: "http://www.dyndns.org/cgi-bin/check_ip.cgi") else {
              return
          }
      
          let session = NSURLSession.sharedSession()
      
          let task = session.dataTaskWithURL(ipServiceURL, completionHandler: {(data, response, error) -> Void in
              if error != nil {
                  print(error)
                  return
              }
      
              let ipHTML = NSString(data: data!, encoding: NSUTF8StringEncoding) as? String
      
              self.ipAddress = self.scanForIPAddress(ipHTML)
      
          })
      
          task.resume()
      }
      
      func scanForIPAddress(var ipHTML:String?) -> String? {
      
          if ipHTML == nil {
              return nil
          }
      
          var externalIPAddress:String?
          var index:Int?
          var ipItems:[String]?
          var text:NSString?
      
          let scanner = NSScanner(string: ipHTML!)
      
          while scanner.atEnd == false {
              scanner.scanUpToString("<", intoString: nil)
      
              scanner.scanUpToString(">", intoString: &text)
      
              ipHTML = ipHTML!.stringByReplacingOccurrencesOfString(String(text!) + ">", withString: " ")
      
              ipItems = ipHTML!.componentsSeparatedByString(" ")
      
              index = ipItems!.indexOf("Address:")
              externalIPAddress = ipItems![++index!]
      
          }
      
          if let ip = externalIPAddress {
              print("External IP Address: \(ip)")
          }
      
          return externalIPAddress
      
      }
      

      【讨论】:

        【解决方案6】:

        您可以调用公共 IP 地址查找服务来获取此信息吗?我已将http://ipof.in 设置为以 JSON/XML 或纯文本形式返回设备 IP 地址的服务。你可以在这里找到它们

        对于带有 GeoIP 数据的 JSON

        http://ipof.in/json

        https://ipof.in/json

        对于 XML 响应

        http://ipof.in/xml

        https://ipof.in/xml

        纯文本IP地址

        http://ipof.in/txt

        https://ipof.in/txt

        【讨论】:

          【解决方案7】:

          我使用ipify,没有任何抱怨。

          NSURL *url = [NSURL URLWithString:@"https://api.ipify.org/"];
          NSString *ipAddress = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
          NSLog(@"My public IP address is: %@", ipAddress);
          

          【讨论】:

            【解决方案8】:

            您必须查询外部服务器才能找到公共 IP。设置您自己的服务器(1 行 php 代码)或使用许多可用服务器之一,这些服务器在 http 查询时将 IP 作为纯文本或 json 返回。比如http://myipdoc.com/ip.php

            【讨论】:

              【解决方案9】:

              我发现 Andrei 和 Tarek 的回答都很有帮助。 两者都依赖 Web URL 来查询 iOS/OS X 设备的“公共 IP”。

              但是,在世界某些地方,这种方法存在一个问题,如“http://www.dyndns.org/cgi-bin/check_ip.cgi”之类的 URL 被审查,如安德烈的回答:

              NSString *theIpHtml = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.dyndns.org/cgi-bin/check_ip.cgi"]
              encoding:NSUTF8StringEncoding
                                                                error:&error];
              

              在这种情况下,我们需要在区域内使用“未经审查”的 URL,例如 http://1212.ip138.com/ic.asp

              请注意,Web URL 可以使用与 Andrei 的答案可以解析的不同的 HTML 和编码 - 在上面的 URL 中,一些非常温和的更改可以通过使用 kCFStringEncodingGB_18030_2000 来修复它http://1212.ip138.com/ic.asp

              NSURL* externalIPCheckURL = [NSURL URLWithString: @"http://1212.ip138.com/ic.asp"];
              encoding:NSUTF8StringEncoding error:nil];
              
              NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
              
              NSString *theIpHtml = [NSString stringWithContentsOfURL: externalIPCheckURL
                                                                 encoding: encoding
                                                                    error: &error];
              

              【讨论】:

              • 你好雨神;这是有用的信息,但它本身并不是一个完整的答案 - 所以它应该作为对您所引用的其他一个或两个答案的评论发布。目前,您没有足够的声誉来制作 cmets;现在,您需要发布有用的问题和有用的完整答案,以获得添加 cmets 的声誉。
              猜你喜欢
              • 1970-01-01
              • 2013-06-29
              • 2021-04-04
              • 1970-01-01
              • 2020-05-06
              • 2019-02-09
              • 1970-01-01
              • 1970-01-01
              • 2019-08-14
              相关资源
              最近更新 更多