如何获取设备的公共IP地址

18

我发现这段示例代码可以获取所有本地IP地址,但我没有找到一个简单的解决方案来获取公共IP。

苹果的一个遗留类允许这样做......但它已经过时了...

9个回答

23

就是这么简单:

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

1
它能够工作,这是获得IP地址的简短和简单方法!!谢谢。 - Shikha Sharma
6
哈哈哈,我不知道我有多相信一个以icanhazip.com为域名的网站的长久性。 :) - CIFilter
5
icanhazip.com其实是Backspace公司员工创建的一个非常知名的服务,已经运行了很多年(至少7年)。想要了解更多信息,请查看此链接:icanhazip FAQ - Tarek
在Swift中,我在这里回答了[https://dev59.com/UpDea4cB1Zd3GeqPfbc9#63280838]。 - Taras

9
我以前使用过 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;
    }
}

Source from ALSystemUtilities


我们没有调用它就找不到它吗? - Damien Romito
9
如果你说的“公共IP”是指“互联网看到我的IP地址来源”,那么没有办法知道,除非向互联网的某个部分询问。NAT不会在你的设备上发生,而是发生在网络中。请注意,不同的设备可能会根据你的路由方式(包括一些设备可能将你看作具有IPv4地址,而其他设备则认为你具有IPv6地址)而视你具有不同的IP地址。"互联网"只是一个特定的网络;你可以连接并在许多不同的网络之间进行路由,其中包括不同的IP映射。 - Rob Napier

7

感谢 @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地址。 我使用的网站是商业公司的网站,因此,只要该业务存在,它就会存在。

注2:您可以自己创建一些网站,但是苹果要求HTTPS网站才能使用此功能。


关于你的NOTE2,苹果目前尚未强制要求使用HTTPS,因此它们可以是HTTP网站。 - Andy Ibanez

2

我使用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);

2

对于我们使用Swift的人来说,这里是Andrei答案的翻译,并增加了NSURLSession以在后台运行。我使用Reachability.swift来检查网络。另外,请记得在你的info.plist中将dyndns.org添加到NSExceptionDomains以用于NSAppTransportSecurity

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

}

2
如果您想异步检索IP,可以使用ipify.org和Alamofire在1行代码中完成:
Alamofire.request("https://api.ipify.org").responseString { (response) in
    print(response.result.value ?? "Unable to get IP")
}

1

0

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

然而,在一些地区,像Andrei回答中提到的那样,这种方法存在问题,因为像“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
请注意,网页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];

嗨,Yushen;这是有用的信息,但本身并不是完整的答案 - 因此,它应该作为评论发布在您所提到的其他答案中的一个或两个上。目前,您没有足够的声望来发表评论;现在,您需要努力发布有用的问题和完整的答案,以赚取声望来添加评论。 - Vince Bowdren

0
你需要查询外部服务器以获取公共IP。可以设置自己的服务器(1行php代码),也可以使用其中一个可用的服务器,该服务器在http查询时返回纯文本或json格式的IP地址,例如http://myipdoc.com/ip.php

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接