2012-02-10 2 views
5

Выполняли поиск по Google и некоторые чтения по этому вопросу, но, похоже, не могут понять, сколько времени я провел в поиске.UDP-трансляция с использованием CFSocket на IOS

Что я хочу сделать, так это получать широковещательные сообщения о устройствах, подключенных к моей сети, рекламируя мой интерес к их услугам, которые они предоставляют. Используя wirehark, я могу видеть сообщения широковещания/уведомления от сетевых устройств, которые я хочу подключить для отправки по моей сети, но не для моего широковещательного поиска интереса к их услугам. Но с сетевой утилитой я вижу, что сокет создан, но не знает, в каком состоянии он находится, будь то прослушивание или подключение.

Да, я знаю, что есть библиотеки, которые я могу использовать для этого, но я хотел создать что-то свое с нуля и лучше понять, как это работает.

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 

Edit: Все работает хорошо, пока вызов не для передачи данных.

Есть ли что-то маленькое, но важное для того, чтобы это работало, что мне не хватает? Или мне не хватает большой картины?

Любая помощь или руководство оценены. Спасибо заранее и иметь хорошие выходные

ответ

0

Как об использовании инициализации с адресом

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

удалить SetAdress и все будет работать нормально. Я тестировал это сейчас;

Смежные вопросы