1

在我的应用程序中,我需要获取一个 NSString 对象值,该值等于用户公共/互联网 IP 地址的值。我已经尝试过解决这个问题的方法,但两者都返回本地 IP 地址不公开。下面是我的两种方法。一种更精确,并且始终返回数组中的正确项。另一个没有。(因为只是选择一个随机索引)......

- (NSString *)getPublicIP {   
    NSHost *publicIP = [[[NSHost currentHost] addresses] objectAtIndex:0];
    return publicIP;  
}

其他更准确的:(但没有获得公共IP)

 //start get ip
- (NSString *)getIPWithNSHost { 

NSArray *addresses = [[NSHost currentHost] addresses];
NSString *stringAddress;
for (NSString *anAddress in addresses) {
    if (![anAddress hasPrefix:@"127"] && [[anAddress componentsSeparatedByString:@"."] count] == 4) {
    stringAddress = anAddress;
    break;
    }
    else {
    stringAddress = @"IPv4 address not available" ;

}
    //NSLog(stringAddress);
}
NSLog (@"getIPWithNSHost: stringAddress = %@ ",stringAddress); 
stringAddress = (@"getIPWithNSHost: stringAddress = %@ ",stringAddress);

return  stringAddress;

}

无论哪种方式,我只需要一种方法来获取外部/公共/互联网 IP 地址。(只是为了澄清外部/公共/互联网 ip 是可以从 whatsmyip.org 检索到的)

4

6 回答 6

5

这是 joshbillions 答案的 iOS 友好版本:

+(void)getPublicIP:(void(^)(NSString *))block {
    NSURL *url = [NSURL URLWithString:@"http://checkip.dyndns.org"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [[[NSURLSession sharedSession]dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error) {
            // consider handling error
        } else {
            NSString *html = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
            NSCharacterSet *numbers = [NSCharacterSet characterSetWithCharactersInString:@"0123456789."];
            NSString *ipAddr = [[html componentsSeparatedByCharactersInSet:numbers.invertedSet]componentsJoinedByString:@""];
            if (block) {
                block(ipAddr);
            }
        }
    }]resume];
}
于 2015-03-22T14:21:36.637 回答
4

由于NAT,您不能指望您的机器在其任何接口上都可以使用其外部 IP。
获取您的外部 IP 的唯一半可靠方法是询问 Internet 上的一台机器(如您提到的 whatsmyip.org),该机器在通过任何本地路由器/防火墙后查看您的 IP 流量。

例如,在 IP 电话中使用的一种要求此信息的标准方法是使用STUN 协议

于 2012-04-28T06:09:53.443 回答
4

它像罪恶一样丑陋,但这对我有用:

NSTask *task = [[[NSTask alloc] init] autorelease];
[task setLaunchPath:@"/usr/bin/curl"];
[task setArguments:[NSArray arrayWithObjects:@"-s",@"http://checkip.dyndns.org", nil]];
NSPipe *outputPipe = [NSPipe pipe];
[task setStandardOutput:outputPipe];
[task launch];
NSData *curlData = [[outputPipe fileHandleForReading] readDataToEndOfFile];
NSString *curlString = [[NSString alloc] initWithData:curlData encoding:NSASCIIStringEncoding];
NSMutableString *strippedString = [NSMutableString
                                   stringWithCapacity:curlString.length];

NSScanner *scanner = [NSScanner scannerWithString:curlString];
NSCharacterSet *numbers = [NSCharacterSet
                           characterSetWithCharactersInString:@"0123456789."];

while ([scanner isAtEnd] == NO) {
    NSString *buffer;
    if ([scanner scanCharactersFromSet:numbers intoString:&buffer]) {
        [strippedString appendString:buffer];

    } else {
        [scanner setScanLocation:([scanner scanLocation] + 1)];
    }
}
NSLog(@"IP Address: %@", strippedString);
于 2013-01-21T22:08:54.370 回答
3

STUN 协议是获取公共 IP 和端口的好解决方案 - 查看 iOS 的 STUN 协议实现https://github.com/soulfly/STUN-iOS

于 2012-09-20T19:19:01.717 回答
1
  • get除非您通过引用传递参数,否则方法永远不应使用前缀...

但这并不能回答你的问题。

回答需要一个问题;你想做什么?

除了最有限的情况外,您设备的 IP 地址很可能毫无意义。

  • 如果在蜂窝网络上,它可能无法路由

  • 如果在任何类型的消费者互联网连接上,它可能位于某种 NAT 路由器后面

  • 即使在极少数情况下获得可路由地址,您的设备也可能位于防火墙后面

除了最罕见的 [通常是管理密集型案例] 之外,您应该使用 Bonjour 进行非以 IP 为中心的服务发现或类似 Game Center 的东西来进行人对人匹配(或其他特定于域的匹配代理)。

于 2012-04-28T06:09:39.763 回答
0

我使用ifconfig.me,这是一个很棒的站点,可以使用多种输出格式(包括 JSON)来获取您的公共 IP 地址和其他信息。

- (void)myPublicIPAddressWithCompletitionBlock:(void (^)(NSString *))completitionBlock {
    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    [sessionConfiguration setHTTPAdditionalHeaders:@{@"Content-Type": @"application/json"}];

    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];

    NSURL *url = [NSURL URLWithString:@"https://ifconfig.me/all.json"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (!error) {
            NSError *jsonError = nil;
            NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
            if (!jsonError) {
                if (jsonResponse[@"ip_addr"]) {
                    if (completitionBlock) {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            completitionBlock(jsonResponse[@"ip_addr"]);
                        });
                    }

                    return ;
                }
            }
        }

        if (completitionBlock) {
            dispatch_async(dispatch_get_main_queue(), ^{
                completitionBlock(@"none");
            });
        }
    }];

    [task resume];
}
于 2020-06-11T00:57:01.357 回答