Objective c 如何获取Mac OS网络配置 背景
我正在开发一个应用程序来监控公司网络中的机器。 每台机器都将运行我的应用程序,它会跟踪许多有关机器状态的信息 我想跟踪的事情之一是网络配置Objective c 如何获取Mac OS网络配置 背景,objective-c,macos,Objective C,Macos,我正在开发一个应用程序来监控公司网络中的机器。 每台机器都将运行我的应用程序,它会跟踪许多有关机器状态的信息 我想跟踪的事情之一是网络配置 网络接口列表 ipv4 ipv6 名字 问题: 我可以获取网络设备列表(),或者获取其MAC地址或BSD名称 我在获取两个协议(IPv4和IPv6)的机器IP地址信息时遇到问题 我尝试了使用和,但只有空值和返回值 在SCNetworkInterfaceGetTextEndedConfiguration的情况下,我使用了以下值:kSCEntNetIPSec
- 网络接口列表
- ipv4
- ipv6
- 名字
SCNetworkInterfaceGetTextEndedConfiguration
的情况下,我使用了以下值:kSCEntNetIPSec
,kSCEntNetIPv4
,kSCEntNetIPv6
文档不够精确和清晰,所以我知道这个API在哪里使用,这给了我一些提示,但仍然没有帮助
我做错了什么
这里我用一些测试代码来探索API(它是C++代码,因为我移植到MAC):
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
内联作废myRelease(CFTypeRef p)
{
如果(p)CFP释放(p);
}
内联标准::字符串toStd(CFStringRef s)
{
如果(!s){
返回{};
}
if(auto fastCString=CFStringGetCStringPtr(s,kcfstringcodingutf8)){
返回快速字符串;
}
自动长度=CFStringGetLength(s);
自动大小=CFStringGetMaximumSizeForncoding(CFStringGetLength,kCFStringEncodingUTF8)+1;
std::字符串结果(大小,'\0');
CFStringGetBytes(s,{0,len},kCFStringEncodingUTF8',?',0,
重新解释_cast(&result[0]),result.size(),&size);
结果:调整大小(大小);
返回结果;
}
std::奥斯特拉姆和操作员感谢@Hofi和@johnelemans的帮助。这些暗示足以找到答案。
对于可能存在类似问题的其他人:
要获取Mac地址,必须使用。我可以从中获取连接详细信息,稍后需要这些信息
现在API的使用有点奇怪。
要探索可以做什么,可以使用命令行工具:。
最好在没有参数的情况下运行它,并键入以下命令:
list
list State:/Network/Interfaces/.*
get State:/Network/Interface/en0/IPv6
d.show
我找到了
根据从这个工具获得的信息,我想出了如何获取所需的数据。
C++中的测试代码:
#include <iostream>
#include <string>
#include <SystemConfiguration/SystemConfiguration.h>
#include <CoreFoundation/CoreFoundation.h>
inline void myRelease(CFTypeRef p)
{
if (p) CFRelease(p);
}
inline std::string toStd(CFStringRef s)
{
if (!s) {
return {};
}
if (auto fastCString = CFStringGetCStringPtr(s, kCFStringEncodingUTF8)) {
return fastCString;
}
auto len = CFStringGetLength(s);
auto size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(s), kCFStringEncodingUTF8) + 1;
std::string result(size, '\0');
CFStringGetBytes(s, { 0, len }, kCFStringEncodingUTF8, '?', 0,
reinterpret_cast<UInt8 *>(&result[0]), result.size(), &size);
result.resize(size);
return result;
}
std::ostream &operator<<(std::ostream &out, CFStringRef s) {
return out << toStd(s);
}
struct DebugCf {
DebugCf(CFTypeRef p) : mP(p) {}
std::string toString() const {
if (!mP) {
return "<null>";
}
auto idOfType = CFGetTypeID(mP);
if (CFStringGetTypeID() == idOfType) {
return toStd((CFStringRef)mP);
}
auto s = CFCopyDescription(mP);
auto result = toStd(s);
CFRelease(s);
return result;
}
private:
CFTypeRef mP;
};
std::ostream &operator<<(std::ostream &out, const DebugCf d) {
return out << d.toString();
}
#define LOGCF(x) " " #x "["<< DebugCf(x) << "], "
std::string SCErrorString()
{
switch (SCError()) {
case kSCStatusOK: return "OK";
case kSCStatusFailed: return "Failed";
case kSCStatusInvalidArgument: return "InvalidArgument";
case kSCStatusAccessError: return "AccessError";
case kSCStatusNoKey: return "NoKey";
case kSCStatusKeyExists: return "KeyExists";
case kSCStatusLocked: return "Locked";
case kSCStatusNeedLock: return "NeedLock";
case kSCStatusNoStoreSession: return "NoStoreSession";
case kSCStatusNoStoreServer: return "NoStoreServer";
case kSCStatusNotifierActive: return "NotifierActive";
case kSCStatusNoPrefsSession: return "NoPrefsSession";
case kSCStatusPrefsBusy: return "PrefsBusy";
case kSCStatusNoConfigFile: return "NoConfigFile";
case kSCStatusNoLink: return "NoLink";
case kSCStatusStale: return "Stale";
case kSCStatusMaxLink: return "MaxLink";
case kSCStatusReachabilityUnknown: return "ReachabilityUnknown";
default:
return std::to_string(SCError());
}
}
void exploreServiceQuery(CFStringRef query, CFStringRef serviceId, SCDynamicStoreRef scSession) {
auto resolvedQuery =
CFStringCreateWithFormat(kCFAllocatorDefault,
NULL,
query, serviceId);
auto dic = (CFDictionaryRef)SCDynamicStoreCopyValue(scSession,
resolvedQuery);
std::cout << resolvedQuery << " - " << LOGCF(dic) << '\n';
myRelease(dic);
CFRelease(resolvedQuery);
}
void printIpv4Data(SCDynamicStoreRef scSession,
CFStringRef bsdName) {
exploreServiceQuery(CFSTR("State:/Network/Interface/%@/IPv4"),
bsdName,
scSession);
}
void printIpv6Data(SCDynamicStoreRef scSession,
CFStringRef bsdName) {
exploreServiceQuery(CFSTR("State:/Network/Interface/%@/IPv6"),
bsdName,
scSession);
}
void desiriedData() {
auto allInterfaces = SCNetworkInterfaceCopyAll();
auto scSession = SCDynamicStoreCreate(kCFAllocatorDefault,
CFSTR("Custom"),
NULL,
NULL);
auto count = CFArrayGetCount(allInterfaces);
for (CFIndex i = 0; i < count; ++i) {
auto netInterface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(allInterfaces, i);
auto macString = SCNetworkInterfaceGetHardwareAddressString(netInterface);
auto bsdName = SCNetworkInterfaceGetBSDName(netInterface);
std::cout << bsdName << " " << macString << '\n';
printIpv4Data(scSession, bsdName);
printIpv6Data(scSession, bsdName);
}
CFRelease(scSession);
CFRelease(allInterfaces);
}
int main(int argc, const char * argv[]) {
desiriedData();
return 0;
}
#包括
#包括
#包括
#包括
内联作废myRelease(CFTypeRef p)
{
如果(p)CFP释放(p);
}
内联标准::字符串toStd(CFStringRef s)
{
如果(!s){
返回{};
}
if(auto fastCString=CFStringGetCStringPtr(s,kcfstringcodingutf8)){
返回快速字符串;
}
自动长度=CFStringGetLength(s);
自动大小=CFStringGetMaximumSizeForncoding(CFStringGetLength,kCFStringEncodingUTF8)+1;
std::字符串结果(大小,'\0');
CFStringGetBytes(s,{0,len},kCFStringEncodingUTF8',?',0,
重新解释_cast(&result[0]),result.size(),&size);
结果:调整大小(大小);
返回结果;
}
标准:奥斯特雷姆和运营商FWIW;我在swift中写下了这一点,对于SCNetworkInterfaceGetConfiguration和扩展调用,它也返回nil。这种方法是否可行;你查过菜单的来源了吗@谢谢,这很有帮助
#include <iostream>
#include <string>
#include <SystemConfiguration/SystemConfiguration.h>
#include <CoreFoundation/CoreFoundation.h>
inline void myRelease(CFTypeRef p)
{
if (p) CFRelease(p);
}
inline std::string toStd(CFStringRef s)
{
if (!s) {
return {};
}
if (auto fastCString = CFStringGetCStringPtr(s, kCFStringEncodingUTF8)) {
return fastCString;
}
auto len = CFStringGetLength(s);
auto size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(s), kCFStringEncodingUTF8) + 1;
std::string result(size, '\0');
CFStringGetBytes(s, { 0, len }, kCFStringEncodingUTF8, '?', 0,
reinterpret_cast<UInt8 *>(&result[0]), result.size(), &size);
result.resize(size);
return result;
}
std::ostream &operator<<(std::ostream &out, CFStringRef s) {
return out << toStd(s);
}
struct DebugCf {
DebugCf(CFTypeRef p) : mP(p) {}
std::string toString() const {
if (!mP) {
return "<null>";
}
auto idOfType = CFGetTypeID(mP);
if (CFStringGetTypeID() == idOfType) {
return toStd((CFStringRef)mP);
}
auto s = CFCopyDescription(mP);
auto result = toStd(s);
CFRelease(s);
return result;
}
private:
CFTypeRef mP;
};
std::ostream &operator<<(std::ostream &out, const DebugCf d) {
return out << d.toString();
}
#define LOGCF(x) " " #x "["<< DebugCf(x) << "], "
std::string SCErrorString()
{
switch (SCError()) {
case kSCStatusOK: return "OK";
case kSCStatusFailed: return "Failed";
case kSCStatusInvalidArgument: return "InvalidArgument";
case kSCStatusAccessError: return "AccessError";
case kSCStatusNoKey: return "NoKey";
case kSCStatusKeyExists: return "KeyExists";
case kSCStatusLocked: return "Locked";
case kSCStatusNeedLock: return "NeedLock";
case kSCStatusNoStoreSession: return "NoStoreSession";
case kSCStatusNoStoreServer: return "NoStoreServer";
case kSCStatusNotifierActive: return "NotifierActive";
case kSCStatusNoPrefsSession: return "NoPrefsSession";
case kSCStatusPrefsBusy: return "PrefsBusy";
case kSCStatusNoConfigFile: return "NoConfigFile";
case kSCStatusNoLink: return "NoLink";
case kSCStatusStale: return "Stale";
case kSCStatusMaxLink: return "MaxLink";
case kSCStatusReachabilityUnknown: return "ReachabilityUnknown";
default:
return std::to_string(SCError());
}
}
void exploreServiceQuery(CFStringRef query, CFStringRef serviceId, SCDynamicStoreRef scSession) {
auto resolvedQuery =
CFStringCreateWithFormat(kCFAllocatorDefault,
NULL,
query, serviceId);
auto dic = (CFDictionaryRef)SCDynamicStoreCopyValue(scSession,
resolvedQuery);
std::cout << resolvedQuery << " - " << LOGCF(dic) << '\n';
myRelease(dic);
CFRelease(resolvedQuery);
}
void printIpv4Data(SCDynamicStoreRef scSession,
CFStringRef bsdName) {
exploreServiceQuery(CFSTR("State:/Network/Interface/%@/IPv4"),
bsdName,
scSession);
}
void printIpv6Data(SCDynamicStoreRef scSession,
CFStringRef bsdName) {
exploreServiceQuery(CFSTR("State:/Network/Interface/%@/IPv6"),
bsdName,
scSession);
}
void desiriedData() {
auto allInterfaces = SCNetworkInterfaceCopyAll();
auto scSession = SCDynamicStoreCreate(kCFAllocatorDefault,
CFSTR("Custom"),
NULL,
NULL);
auto count = CFArrayGetCount(allInterfaces);
for (CFIndex i = 0; i < count; ++i) {
auto netInterface = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(allInterfaces, i);
auto macString = SCNetworkInterfaceGetHardwareAddressString(netInterface);
auto bsdName = SCNetworkInterfaceGetBSDName(netInterface);
std::cout << bsdName << " " << macString << '\n';
printIpv4Data(scSession, bsdName);
printIpv6Data(scSession, bsdName);
}
CFRelease(scSession);
CFRelease(allInterfaces);
}
int main(int argc, const char * argv[]) {
desiriedData();
return 0;
}