2012-02-10 73 views
5

已經做了一些谷歌搜索和一些關於這個主題的閱讀,但無論我花了多少時間搜索,似乎都無法做到。使用IOS上的CFSocket進行UDP廣播

我想要做的就是通過廣告我對他們提供的服務的興趣來接收在我的網絡上連接的設備的廣播消息。使用wireshark,我可以看到來自想要連接的網絡設備的廣播/通知消息,這些消息是通過我的網絡發送的,但不是我的廣播搜索對其服務的興趣。 但與網絡實用程序,我可以看到套接字創建,但不知道它是在哪個狀態,無論是聽或連接。

是的,我知道有些庫可以用來做這件事,但我想從頭開始構建自己的東西,並更好地理解它是如何工作的。

MySocket.h

#import <Foundation/Foundation.h> 
#import <CoreFoundation/CoreFoundation.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#if TARGET_OS_IPHONE 
#import <CFNetwork/CFNetwork.h> 
#endif 

@interface MySocket : NSObject 
{ 
    NSString* _message; 
    CFSocketRef cfSocket; 
    CFRunLoopSourceRef cfSource; 

} 

- (void)listen; 
@end 

MySocket.m

#import "MySocket.h" 

#define MAX_UDP_DATAGRAM_SIZE 65507 

@implementation MySocket 


static void socketCallback(CFSocketRef cfSocket, CFSocketCallBackType 
          type, CFDataRef address, const void *data, void *userInfo) 
{ 
    NSLog(@"socketCAllBAck was called"); 
}  

- (void)listen 
{ 
    //Enable broadcast to network hosts   
    int yes = 1; 
    int setSockResult = 0; 
    _message = [[NSMutableString alloc ] initWithString: @"M-SEARCH *HTTP/1.1\r\nHOST:239.255.255.250:1900\r\nMAN:\"ssdp:discover\"\r\nST:ssdp:all\r\nMX:1\r\n\r\n"]; 

    CFSocketContext socketContext = {0, self, NULL, NULL, NULL}; 

    /* Create the server socket as a UDP IPv4 socket and set a callback */ 
    /* for calls to the socket's lower-level accept() function */ 
    cfSocket = CFSocketCreate(NULL, PF_INET, SOCK_DGRAM, IPPROTO_UDP, 
           kCFSocketAcceptCallBack | kCFSocketDataCallBack , (CFSocketCallBack)socketCallback, &socketContext); 
    if (cfSocket == NULL) 
     NSLog(@"UDP socket could not be created\n"); 

    /* Re-use local addresses, if they're still in TIME_WAIT */ 
    setSockResult = setsockopt(CFSocketGetNative(cfSocket), SOL_SOCKET, SO_BROADCAST, (void *)&yes, sizeof(yes)); 

    if(setSockResult < 0) 
     NSLog(@"Could not setsockopt for broabcast"); 

    /* Set the port and address we want to listen on */ 
    struct sockaddr_in addr; 
    memset(&addr, 0, sizeof(addr)); 
    addr.sin_len = sizeof(addr); 
    addr.sin_family = AF_INET; 
    addr.sin_addr.s_addr = inet_addr("239.255.255.250"); 
    //inet_pton(AF_INET, "239.255.255.250", &(addr.sin_addr)); 

    addr.sin_port = htons(1900); 
    //addr.sin_addr.s_addr = htonl(INADDR_ANY); 

    NSData *address = [ NSData dataWithBytes: &addr length: sizeof(addr) ]; 
    if (address != nil && CFSocketSetAddress(cfSocket, (CFDataRef) address) != kCFSocketSuccess) { 
     NSLog(@"CFSocketSetAddress() failed\n"); 
     CFRelease(cfSocket); 
    }  

    CFDataRef data = CFDataCreate(NULL, (const UInt8*)[_message UTF8String], [_message lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); 

    setSockResult = CFSocketSendData(cfSocket, (CFDataRef)address, data, 0.0); 
    if(kCFSocketSuccess != setSockResult) NSLog(@"Unable to send data, %i", setSockResult); 
    else NSLog(@"Sending data"); 

    cfSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, cfSocket, 0); 

    if(cfSource == NULL) 
     NSLog(@"CFRunLoopSourceRef is null"); 

    CFRunLoopAddSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode); 

    NSLog(@"Socket listening on port 1900"); 

     CFRelease(cfSource); 
    CFRelease(cfSocket); 
    [address release]; 
    data = nil; 
    CFRunLoopRun(); 
} 

- (void)dealloc 
{ 
    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode); 
    CFRelease(cfSource); 
    CFRelease(cfSocket); 
    [_message release]; 
    [super dealloc]; 
} 

@end 

編輯:一切運行良好,直到調用發送數據。

是否有一些小而關鍵的,爲了這個工作,我失蹤了? 或者我錯過了大圖?

任何幫助或指導表示讚賞。 在此先感謝,並有一個愉快的週末

回答

0

如何使用這個初始化與地址

CFDataRef address=CFDataCreate(kCFAllocatorDefault,(UInt8 *)&addr,sizeof(addr)); 
1

刪除SetAdress一切都會做工精細。我現在已經測試過了;