2011-07-22 55 views
4

我試圖確定我的Macbook所在的網段,因爲我想通過使用CFHost類來掃描活動主機(基本IP掃描器)的這一段。因此我需要我的活動界面的IP和網絡掩碼。這是我如何得到的IP:如何在Mac上確定Objective-C中活動接口的網絡掩碼?

NSString *ipAddr = [[[NSHost currentHost] addresses] objectAtIndex:0]; 

但我絕對不知道如何獲得網絡掩碼,所以我有點卡住了。特別是因爲我在Objective-C方面相當新穎,而且我也沒有廣泛的C語言知識。我查看了CFHost,CFNetwork,NSHost和各種Google命中,但迄今爲止沒有發現任何有用的東西。

作爲最後的手段,我可​​以做一個系統調用,我想,或者從一個文件(哪一個?)讀取它,但我想避免這種情況,如果可能的話。

那麼,如何獲得通過NSHost獲得的匹配網絡掩碼?任何建議將不勝感激。

謝謝!

+0

也許是我太狹隘定義這一點。 Objective-C中有沒有一種方法可以通過網絡掩碼或其他方法找出我所在的網段? – Martin

回答

3
+0

謝謝,雖然我還沒有完全測試過。我想這應該是SCNetworkInterfaceGetConfiguration或SCNetworkInterfaceGetExtendedConfiguration,但我不確定這些從參考文檔單獨返回。另外,從我從參考頁面收集的內容中,只有當數據包可以離開本地計算機時,我才能夠掃描主機是否啓動或關閉了CFHost。所以我想我必須實現一個真正的ICMP回顯請求,這對我來說看起來相當複雜。 – Martin

12

因此,爲了解決這個問題,我終於開始研究系統配置API。一如既往,一旦你知道它不那麼困難。

@ 0xced - 感謝您指引我正確的方向。我會贊成你的回答,但我沒有足夠的聲望去做。

這是我的解決方案,適合任何好奇或處於相同情境的人。它涉及挖掘動態商店。請參閱this瞭解API的相關信息。您可以使用scutil命令行實用程序查看動態存儲庫保存的信息(請參閱x-man-page:// 8/scutil)。

這是我的步驟。首先,你需要一個會話:

SCDynamicStoreRef storeRef = SCDynamicStoreCreate(NULL, (CFStringRef)@"FindCurrentInterfaceIpMac", NULL, NULL); 

於是,我試圖讓主接口(EN1爲例):

CFPropertyListRef global = SCDynamicStoreCopyValue (storeRef,CFSTR("State:/Network/Global/IPv4")); 
NSString *primaryInterface = [(__bridge NSDictionary *)global valueForKey:@"PrimaryInterface"]; 

最後,我建立包含接口,以便能夠爲一個字符串查詢右鍵。它應該看起來像State:/ Network/Interface/en1/IPv4,當然取決於接口。有了這個,我可以得到一個數組與IP和網絡掩碼。在我的Macbook上,這些陣列分別僅保存一個IP和網絡掩碼。我想這可能會對其他Mac有所不同,我將不得不驗證。對於我的測試,我只是將第一個(也是唯一的)元素放在數組中,但是在那裏需要執行某種尺寸檢查。

NSString *interfaceState = [NSString stringWithFormat:@"State:/Network/Interface/%@/IPv4", primaryInterface]; 

CFPropertyListRef ipv4 = SCDynamicStoreCopyValue (storeRef, (CFStringRef)interfaceState); 
CFRelease(storeRef); 

NSString *ip = [(__bridge NSDictionary *)ipv4 valueForKey:@"Addresses"][0]; 
NSString *netmask = [(__bridge NSDictionary *)ipv4 valueForKey:@"SubnetMasks"][0]; 
CFRelease(ipv4); 

這只是爲了測試,所以它有點粗糙的邊緣。你將不得不尋找保留計數等。它只是爲了瞭解它是如何完成的。

0

Martin給出了一個很好的答案。
而他在ARC版的代碼是在這裏:

+ (NSDictionary *)primaryIPv4AddressInfoFromSystemConfiguration 
{ 
    SCDynamicStoreRef storeRef = SCDynamicStoreCreate(NULL, (CFStringRef)@"FindCurrentInterfaceIpMac", NULL, NULL); 
    if (!storeRef) 
    { 
     return nil; 
    } 

    NSDictionary *IPv4Dictionary = nil; 
    CFPropertyListRef global = SCDynamicStoreCopyValue(storeRef, CFSTR("State:/Network/Global/IPv4")); 
    id primaryInterface = [(NSDictionary *)CFBridgingRelease(global) valueForKey:@"PrimaryInterface"]; 
    if (primaryInterface) 
    { 
     NSString *interfaceState = @"State:/Network/Interface/"; 
     interfaceState = [[interfaceState stringByAppendingString:(NSString *)primaryInterface] stringByAppendingString:@"/IPv4"]; 
     CFPropertyListRef IPv4PropertyList = SCDynamicStoreCopyValue(storeRef, (__bridge CFStringRef)interfaceState); 
     IPv4Dictionary = (NSDictionary *)CFBridgingRelease(IPv4PropertyList); 
    } 

    CFRelease(storeRef); 
    return IPv4Dictionary; 
} 

+ (NSDictionary *)primaryIPv6AddressInfoFromSystemConfiguration 
{ 
    SCDynamicStoreRef storeRef = SCDynamicStoreCreate(NULL, (CFStringRef)@"FindCurrentInterfaceIpMac", NULL, NULL); 
    if (!storeRef) 
    { 
     return nil; 
    } 

    NSDictionary *IPv6Dictionary = nil; 
    CFPropertyListRef global = SCDynamicStoreCopyValue(storeRef, CFSTR("State:/Network/Global/IPv6")); 
    id primaryInterface = [(NSDictionary *)CFBridgingRelease(global) valueForKey:@"PrimaryInterface"]; 
    if (primaryInterface) 
    { 
     NSString *interfaceState = @"State:/Network/Interface/"; 
     interfaceState = [[interfaceState stringByAppendingString:(NSString *)primaryInterface] stringByAppendingString:@"/IPv6"]; 
     CFPropertyListRef IPv6PropertyList = SCDynamicStoreCopyValue(storeRef, (__bridge CFStringRef)interfaceState); 
     IPv6Dictionary = (NSDictionary *)CFBridgingRelease(IPv6PropertyList); 
    } 

    CFRelease(storeRef); 
    return IPv6Dictionary; 
} 
+0

這個答案非常有幫助,謝謝。 –

相關問題