UDP-трансляция с использованием CFSocket на IOS - PullRequest
5 голосов
/ 10 февраля 2012

Занимался поиском в Google и читал эту тему, но, похоже, не могу понять, как правильно, независимо от того, сколько времени я потратил на поиск.

Что я хочу сделать, так это получать широковещательные сообщения от устройств, которые подключены к моей сети, путем объявления моего интереса к их услугам, которые они предоставляют. Используя 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

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

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

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

Ответы [ 2 ]

1 голос
/ 05 февраля 2014

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

0 голосов
/ 03 июля 2013

Как насчет использования этой инициализации с адресом

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