代码之家  ›  专栏  ›  技术社区  ›  GorillaPatch

如何使用系统配置框架检测MacOS上的IPv4地址更改

  •  0
  • GorillaPatch  · 技术社区  · 6 年前

    我正在尝试使用mac操作系统上的系统配置在mac上出现新的网络接口并为其分配新的IP地址时获取通知。

    我设置它来监视系统配置密钥 State:/Network/Interface 当一个新的网络接口出现或消失时,我会收到一个通知。

    但是,每当在新的网络接口上分配IPv4地址时(例如,通过DHCP),我都希望收到通知。我知道钥匙 State:/Network/Interface/en0/IPv4 正在保存EN0接口的IPv4地址。但是使用手册页中描述的所有IPv4地址的正则表达式 State:/Network/Interface/.*/IPv4 不适用于新接口。

    我已经在GitHub上组装了一个小的最小代码示例,但是也可以使用 scutil 命令行工具。

    Link to demo repository

    主C

    #import <Foundation/Foundation.h>
    #import <SystemConfiguration/SystemConfiguration.h>
    
    /* Callback used if a configuration change on monitored keys was detected.
     */
    void dynamicStoreCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void* __nullable info) {
        CFIndex count = CFArrayGetCount(changedKeys);
        for (CFIndex i=0; i<count; i++) {
            NSLog(@"Key \"%@\" was changed", CFArrayGetValueAtIndex(changedKeys, i));
        }
    }
    
    int main(int argc, const char * argv[]) {
        NSArray *SCMonitoringInterfaceKeys = @[@"State:/Network/Interface.*"];
        @autoreleasepool {
            SCDynamicStoreRef dsr = SCDynamicStoreCreate(NULL, CFSTR("network_interface_detector"), &dynamicStoreCallback, NULL);
            SCDynamicStoreSetNotificationKeys(dsr, CFBridgingRetain(SCMonitoringInterfaceKeys), NULL);
            CFRunLoopAddSource(CFRunLoopGetCurrent(), SCDynamicStoreCreateRunLoopSource(NULL, dsr, 0), kCFRunLoopDefaultMode);
            NSLog(@"Starting RunLoop...");
            while([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
        }
        return 0;
    }
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   GorillaPatch    6 年前

    在一些开发人员同事的帮助下,我发现了问题所在。的签名 SCDynamicStoreSetNotificationKeys 功能如下:

    Boolean SCDynamicStoreSetNotificationKeys (SCDynamicStoreRef store,
                    CFArrayRef          __nullable  keys,
                    CFArrayRef          __nullable  patterns
                    )
    

    这意味着我必须将模式与作为树根的键分开设置,在树根下模式匹配将发生。这是我的修改版 主m :

    int main(int argc, const char * argv[]) {
        NSArray *SCMonitoringInterfaceKeys = @[@"State:/Network/Interface"];
        NSArray *patterns = @[@"en\\d*/IPv4"];
        @autoreleasepool {
            SCDynamicStoreRef dsr = SCDynamicStoreCreate(NULL, CFSTR("network_interface_detector"), &dynamicStoreCallback, NULL);
            SCDynamicStoreSetNotificationKeys(dsr, CFBridgingRetain(SCMonitoringInterfaceKeys), CFBridgingRetain(patterns));
            CFRunLoopAddSource(CFRunLoopGetCurrent(), SCDynamicStoreCreateRunLoopSource(NULL, dsr, 0), kCFRunLoopDefaultMode);
            NSLog(@"Starting RunLoop...");
            while([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
        }
        return 0;
    }
    

    我已经包括了解决方案 into the solved branch of the repo .