2012-02-10 10 views
5

Ho fatto qualche ricerca su google e qualche lettura su questo argomento, ma non riesco a farlo bene, non importa quanto tempo ho passato a cercare.Trasmissione UDP tramite CFSocket su IOS

Quello che voglio fare è ricevere messaggi broadcast di dispositivi che sono collegati sulla mia rete pubblicizzando il mio interesse nei loro servizi che forniscono. Usando wireshark posso vedere i messaggi broadcast/di notifica dai dispositivi di rete che voglio connettere a inviati sulla mia rete ma non la mia ricerca in broadcast per interesse dei loro servizi. Ma con l'utilità di rete posso vedere che il socket è stato creato ma non so in quale stato si trova, se ascoltato o connesso.

Sì, so che ci sono librerie che posso usare per fare questo, ma volevo costruire qualcosa di mio da zero e capire meglio come funziona.

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: Tutto funziona bene fino a quando la chiamata per inviare i dati.

C'è qualcosa di piccolo ma fondamentale per far funzionare tutto ciò che mi manca? O mi manca l'immagine grande?

Qualsiasi aiuto o guida è apprezzato. Grazie in anticipo e hanno un bel weekend

risposta

0

Che ne dite di utilizzo questa inizializzazione con l'indirizzo

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

rimuovere SetAdress e tutto andrà bene il lavoro. ho provato questo ora;