在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.1rnHOST:239.255.255.250:1900rnMAN:"ssdp:discover"rnST:ssdp:allrnMX:1rnrn"];
    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 createdn");
    /* 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() failedn");
        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

编辑:在调用发送数据之前,一切都运行良好。

有没有什么小而关键的东西让我错过了?或者我错过了大局?

感谢任何帮助或指导。提前感谢并度过一个美好的周末

删除SetAdress,一切都会正常工作。我现在已经测试过了;

如何将此初始化与地址一起使用

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

最新更新