ios - 如何自动获取客户端中的IP地址 objective-c

标签 ios objective-c sockets

我有两个 Applaction,一个是客户端(IOS 设备),另一个是服务器(PC 设备)。

我想自动获取客户端(IOS 设备)中的 ip 地址。

我正在使用这行代码来输入 IP 地址

NSString *ipAddressText = @"192.168.211.62";

我不想一直输入 IP 地址,因为 IP 地址大部分时间都会更改。

这是我的代码

  -(void)viewDidLoad{
            [super viewDidLoad];


            NSString *ipAddressText = @"192.148.211.42";

            NSLog(@"Setting up connection to %@ : %i", ipAddressText, 111);
            CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef) ipAddressText, 111, &readStream, &writeStream);
            messages = [[NSMutableArray alloc] init];
            [self open];
        }

    - (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {

        NSLog(@"stream event %lu \n ", streamEvent);

        switch (streamEvent) {

            case NSStreamEventOpenCompleted:
                NSLog(@"Stream opened");
                _connectedLabel.text = @"Connected";
                break;
            case NSStreamEventHasBytesAvailable:

                if (theStream == inputStream)
                {
                    uint8_t buffer[1024];
                    NSInteger len;

                    while ([inputStream hasBytesAvailable])
                    {
                        len = [inputStream read:buffer maxLength:sizeof(buffer)];
                        if (len > 0)
                        {
                            NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];

                            if (nil != output)
                            {
                                NSLog(@"server said: %@ \n ", output);
                                [self messageReceived:output];
                            }
                        }
                    }
                }
                break;

            case NSStreamEventHasSpaceAvailable:
                NSLog(@"Stream has space available now");
                break;

            case NSStreamEventErrorOccurred:
                NSLog(@"%@\n",[theStream streamError].localizedDescription);
                break;

            case NSStreamEventEndEncountered:

                [theStream close];
                [theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
                _connectedLabel.text = @"Disconnected";
                NSLog(@"close stream");
                break;
            default:
                NSLog(@"Unknown event");
        }

    }

        - (void)open {

            NSLog(@"Opening streams.");

            outputStream = (__bridge NSOutputStream *)writeStream;
            inputStream = (__bridge NSInputStream *)readStream;

            [outputStream setDelegate:self];
            [inputStream setDelegate:self];

            [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

            [outputStream open];
            [inputStream open];

             _connectedLabel.text = @"Connected";
        }


    - (void)close {
        NSLog(@"Closing streams.");
        [inputStream close];
        [outputStream close];
        [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [inputStream setDelegate:nil];
        [outputStream setDelegate:nil];
        inputStream = nil;
        outputStream = nil;

        _connectedLabel.text = @"Disconnected";
    }

最佳答案

这是在 Swift 中,但可以很容易地放入任何 Xcode 项目中。

注意:此示例取自 GitHub 项目 Host.swift .

获取有关 Unix 类型系统(如 iOS 或 Mac OS X)中网络接口(interface)的信息需要使用一些神秘的 C API。这些 API 在 中具有不同程度的可见性和 , .

如果您只使用 Objective-C 来定位 macOS,那么 是您最好的解决方案。但是,如果您需要 iOS 兼容性,则必须使用较低级别的 C API,例如 getifaddrs(...) .

如果你想要一个基于解决方案甚至 getifaddrs(...) 都带有一些桥接头要求(使其在框架中无法使用)。

这是一个使用 CFHostsockaddr_in struct 的示例,它可以在 Swift 和 macOS 和 iOS(甚至在框架中)上运行。参见 Host.swift在 GitHib 上获取一个完整的示例。

  1. 使用 CFHost 获取寻址信息,这将是 CFData 对象的 CFArray

    let sockaddrs = CFHostGetAddressing("apple.com", &resolved)?.takeRetainedValue() 
    
  2. 获取第一个对象

    let data = CFArrayGetValueAtIndex(sockaddrs, 0)
    
  3. 将字节转换为 sockaddr 结构

    var storage = sockaddr_storage()
    data.getBytes(&storage, length: sizeof(sockaddr_storage))
    
  4. 然后将sockaddr struct强制放入sockaddr_in struct中以便我们使用它

    let addr = withUnsafePointer(&storage) { UnsafePointer<sockaddr_in>($0).memory
    
  5. 使用inet_ntoa(...) 函数将addr.sin_addr(IP 地址)转换为C 字符串。然后我们可以使用 String(Cstring: encoding:) 来获得 IP 地址的漂亮字符串。

    let address = String(CString: inet_ntoa(addr.sin_addr), encoding: NSUTF8StringEncoding)
    

这是一个名为 Host.swift 的 GitHub 项目我创建的是为了使用上述技术解决这些问题。

关于ios - 如何自动获取客户端中的IP地址 objective-c ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37356700/

相关文章:

iphone - Objective-C中的JSON解析

ios - 如何在 ios 的 Swift 语言中正确安排动画顺序?

objective-c - 在 Interface Builder 中设置接口(interface)并在 for 循环中重用它

python - Python套接字错误

ios - 我如何“通过电子邮件查找我”

objective-c - 为什么我不能注释掉这个字符串?

iphone - 在 iPhone 上对 double 组或 CLLocationDistance 值进行排序

.net - 如何防止 HttpWebRequest 的数据包碎片

c - 在 TCP 服务器的读/写上实现 poll()

ios - PDFKit Swift 控制缩放