Network 상태 감시하기





이번 시간에는 Mac 의 네트워크 상태가 변경되는 것을 감시할 수 있는 프로그램을 만들어 보도록 하겠습니다.


인터넷에 보면, 특정 Host 에 접속을 시도하여, 성공 유무를 가지고 판단하는 방식이 많이 있습니다.

그런데 이런 방식은 네트워크 상태를 체크하는 용도보다는,

서비스 가능 여부를 확인하는 용도가 더 어울립니다.


예를들어, 현재 카카오톡이 서버와 연결이 된 상태인지, 아닌지를 판다하는 용도로 말입니다.


그런데 제가 하려는것은 이런것이 아니라,

순수하게 현재 네트워크 상태가 변경되었는지 유무를 판단하려는 것입니다.


유선랜을 쓰고 있다가 무선랜으로 변경된다든지.

유선랜을 사용하고 있다가, 선을 뽑았다든지.

무선랜의 IP 주소가 변경되었다든지.


등등 네트워크 상태를 모니터링 하려는 것입니다.



//
//  main.m
//  CocoaTest
//
//  Copyright (c) 2012년 __MyCompanyName__. All rights reserved.
//

#import <Foundation/Foundation.h>
#include <CoreServices/CoreServices.h>
#import <SystemConfiguration/SCDynamicStore.h>



void myCallBack	(
SCDynamicStoreRef	store,
CFArrayRef	 changedKeys,
void	 *info
) {
    NSLog(@"Changed");
    CFRunLoopStop(CFRunLoopGetCurrent());
}


int main(int argc, const char * argv[])
{

    @autoreleasepool {
        SCDynamicStoreRef dynStore;
        SCDynamicStoreContext context = {0, NULL, NULL, NULL, NULL};
        
        dynStore = SCDynamicStoreCreate(kCFAllocatorDefault,
                                        CFBundleGetIdentifier(CFBundleGetMainBundle()),
                                        myCallBack,
                                        &context);

        const CFStringRef keys[3] = {
            CFSTR("State:/Network/Interface/.*/IPv4")
        };
        
        CFArrayRef watchedKeys = CFArrayCreate(kCFAllocatorDefault,
                                               (const void **)keys,
                                               1,
                                               &kCFTypeArrayCallBacks);
        
        if (!SCDynamicStoreSetNotificationKeys(dynStore, NULL, watchedKeys)) 
        {
            CFRelease(watchedKeys);
            CFRelease(dynStore);
            dynStore = NULL;
            
            return -1;
        }
        
        CFRelease(watchedKeys);
        
        
        CFRunLoopSourceRef rlSrc = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, dynStore, 0);
        CFRunLoopAddSource(CFRunLoopGetCurrent(), rlSrc, kCFRunLoopDefaultMode);
        
        CFRunLoopRun();
        NSLog(@"Started");
        [NSThread sleepForTimeInterval:10];
        NSLog(@"Remove");
        CFRunLoopRemoveSource(CFRunLoopGetCurrent(), rlSrc, kCFRunLoopDefaultMode);
        [NSThread sleepForTimeInterval:10];
        NSLog(@"Completed");
        
        CFRelease(watchedKeys);
        CFRelease(dynStore);
        CFRelease(rlSrc);
    }
    return 0;
}





GUI 프로그램이 아니라, console application 으로 생성하였기 때문에,

RunLoop 관련된 코드가 들어가 있습니다.


RunLoop 가 이미 실행중인 프로그램에 적용 하실 때에는, 이 부분은 제외하시면 됩니다.






보시다시피, SystemConfiguration 프레임워크를 추가시켜 주어야 합니다.

xcode 의 타겟 속성에 Build Phases 에서 추가시켜 주시면 됩니다.