How to get the public IP address of the device

2019-02-06 17:21发布

问题:

I found this sample code to get all local IP addresses, but I don't find an easy solution to get the public IP.

A legacy class from Apple allowed to do that ... but it's legacy ...

回答1:

I have used ALSystemUtilities in the past. You basically have to make a call externally to find this out.

+ (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



回答2:

It's as simple as this:

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


回答3:

You have to query an external server to find out the public IP. Either set up your own server (1 line of php code) or use one of the many available ones which return the IP as plain text or json upon http query. Like for example http://myipdoc.com/ip.php .



回答4:

For those of us using Swift, here's my translation of Andrei's answer with the addition of NSURLSession to run it in the background. To check the network, I use Reachability.swift. Also, remember to add dyndns.org to NSExceptionDomains for NSAppTransportSecurity in your 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

}


回答5:

You can call a public IP address lookup services to get this? I have set up http://ipof.in as a service that returns the device IP address as JSON / XML or plain text. You can find them here

For JSON with GeoIP data

http://ipof.in/json

https://ipof.in/json

For XML response

http://ipof.in/xml

https://ipof.in/xml

For plain text IP address

http://ipof.in/txt

https://ipof.in/txt



回答6:

I find both Andrei and Tarek's answers helpful. Both are relying a web URL to query the "public IP" of the iOS/OS X device.

However, there is an issue with this approach in some part of the world where URL such as "http://www.dyndns.org/cgi-bin/check_ip.cgi" is censored as in andrei's answer:

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

In this case, we will need to use an "uncensored" URL within the region such as http://1212.ip138.com/ic.asp

Note that the web URL could use a different HTML and encoding than what Andrei's answer could parse - in the URL above, some very gentle changes can fix it by using kCFStringEncodingGB_18030_2000 for 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];


回答7:

I use ipify and with no complaints.

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