【发布时间】:2015-02-26 19:42:12
【问题描述】:
我找到了this sample code 来获取所有本地 IP 地址,但我没有找到一个简单的解决方案来获取公共 IP。
来自 Apple 的 legacy class 允许这样做 ...但它是遗产...
【问题讨论】:
标签: ios objective-c ip-address public
我找到了this sample code 来获取所有本地 IP 地址,但我没有找到一个简单的解决方案来获取公共 IP。
来自 Apple 的 legacy class 允许这样做 ...但它是遗产...
【问题讨论】:
标签: ios objective-c ip-address public
就这么简单:
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
【讨论】:
icanhazip.com 的网站的寿命有多信任。 :)
icanhazip.com 实际上是 Backspace 员工的一项非常知名的服务,并且已经运行多年(至少 7 年)。欲了解更多信息,请查看此链接:icanhazip FAQ
我过去使用过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;
}
}
【讨论】:
感谢@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站点才能使用此功能。
【讨论】:
如果您想异步检索 IP,有一种方法可以在 1 行代码中使用 ipify.org 和 Alamofire:
Alamofire.request("https://api.ipify.org").responseString { (response) in
print(response.result.value ?? "Unable to get IP")
}
【讨论】:
对于我们这些使用 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
}
【讨论】:
您可以调用公共 IP 地址查找服务来获取此信息吗?我已将http://ipof.in 设置为以 JSON/XML 或纯文本形式返回设备 IP 地址的服务。你可以在这里找到它们
对于带有 GeoIP 数据的 JSON
对于 XML 响应
纯文本IP地址
【讨论】:
我使用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);
【讨论】:
您必须查询外部服务器才能找到公共 IP。设置您自己的服务器(1 行 php 代码)或使用许多可用服务器之一,这些服务器在 http 查询时将 IP 作为纯文本或 json 返回。比如http://myipdoc.com/ip.php。
【讨论】:
我发现 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];
【讨论】: