2016-05-20 232 views
1

我有兩個Applaction,一個是客戶端(IOS設備),另一個是服務器(PC設備)。如何在客戶端自動獲取客戶端的IP地址c

我想在客戶端(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"; 
    } 
+0

這是DNS是 – Paulw11

+0

@ Paulw11有沒有辦法從服務器自動讀取IP地址。謝謝 –

+0

如果他們是你可以使用一個廣播/多播協議像卓悅 – Paulw11

回答

1

這是斯威夫特,但可以輕鬆地投進任何Xcode項目。

注意:本示例取自GitHub項目Host.swift

獲取有關Unix類型系統(如iOS或Mac OS X)中網絡接口的信息需要使用一些神祕的C API。這些API在,中具有不同的可見度。

如果您專門用Objective-C定位macOS,那麼是您的最佳解決方案。但是,如果您需要iOS兼容性,那麼您必須下降到較低級別的C API,例如getifaddrs(...)

如果你想要一個基礎的解決方案,甚至getifaddrs(...)帶有一些橋接報要求(使它在框架不可用)。

這裏是一個使用CFHostsockaddr_in struct的例子,它們可以在Swift和macOS和iOS(甚至在框架中)中工作。有關完整的示例,請參閱GitHib上的Host.swift

  1. 使用CFHost得到解決的信息,這將是CFDataCFArray OBJETS。

    let sockaddrs = CFHostGetAddressing("apple.com", &resolved)?.takeRetainedValue() 
    
  2. 獲得的第一個對象

    let data = CFArrayGetValueAtIndex(sockaddrs, 0) 
    
  3. 演員字節爲sockaddr struct

    var storage = sockaddr_storage() 
    data.getBytes(&storage, length: sizeof(sockaddr_storage)) 
    
  4. 然後迫使sockaddr structsockaddr_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的項目,我創建解決使用上述技術的這些問題。