在Objective-C中获取公共IP?

问题描述 投票:1回答:6

在我的应用程序中,我需要得到一个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;

}

不管是哪种方式,我只是需要一种方法来获得externalpublicinternet的ip地址。(先说明一下,externalpublicinternet ip是可以从watsmyip.org获取的地址)

objective-c ip ip-address external
6个回答
5
投票

这里是一个iOS友好版本的joshbillions的答案。

+(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];
}

4
投票

由于 北约 你不能指望你的机器在任何一个接口上都有它的外部IP。获取外部IP的唯一半可靠的方法是询问互联网上的一台机器(比如你提到的whatsmyip.org),它可以在通过任何本地路由器防火墙后看到你的IP流量。

一个比较标准的方式来询问这个信息,例如在IP电话中使用的是使用 STUN协议.


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);

3
投票

STUN协议是一个很好的解决方案,以获得你的公共IP和端口 - 检查STUN协议实现的iOS。https:/github.comsoulflySTUN-iOS。


1
投票
  • 方法的前缀绝对不应该是 get 除非你是通过引用传递参数... ...

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

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

在所有有限的情况下,你的设备的IP地址很可能毫无意义。

  • 如果是在蜂窝网络上,它可能是不可路由的。

  • 如果在任何类型的消费互联网连接,它可能是背后的NAT路由器的一些类型

  • 即使在极少的情况下被赋予一个可路由地址,你的设备很可能在防火墙后面

除了最罕见的[一般来说是管理密集型的情况],你应该使用Bonjour来做非IP中心的服务发现,或者使用像Game Center这样的东西来做人与人的匹配(或者其他的,域特定的,匹配代理)。


0
投票

我使用 ifconfig.me, 一个伟大的网站来获取你的公共IP地址和其他信息,使用多种输出格式(包括JSON)。

- (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];
}
© www.soinside.com 2019 - 2024. All rights reserved.