Широковещательная передача UDP с использованием CFSocket на IOS

Я выполнял поиск в 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

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

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

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


person Alyek    schedule 10.02.2012    source источник


Ответы (2)


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

person Oleksii Moiseenko    schedule 04.02.2014

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

CFDataRef address=CFDataCreate(kCFAllocatorDefault,(UInt8 *)&addr,sizeof(addr));
person anonymous developer    schedule 03.07.2013