在IOS上使用CFSocket进行UDP广播 [英] UDP broadcast using CFSocket on IOS

查看:582
本文介绍了在IOS上使用CFSocket进行UDP广播的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一直在做一些谷歌搜索和一些关于这个主题的阅读,但无论我花了多少时间搜索,似乎无法做到正确。

Have been doing some google search and some reading on this subject but cannot seem to get it right no matter how much time i spent searching.

我想做的是通过宣传我对他们提供的服务的兴趣来接收我网络上连接的设备的广播消息。使用wireshark,我可以看到来自我想通过网络发送的网络设备的广播/通知消息,但不能通过我的广播搜索来查看他们服务的兴趣。
但是通过网络实用程序,我可以看到套接字已创建,但不知道它处于哪种状态,无论是监听还是已连接。

What i want to do is to receive broadcast message of devices that are connected on my network by advertising my interest in their services that they supply. Using wireshark i can see the broadcast/notification messages from the network devices that i want to connect to sent over my network but not my broadcast search for interest of their services. But with network utility i can see that the socket is created but don't know which state it is in, whether listen or connected.

是的,我知道我可以用它来做这个库,但我想从头开始构建我自己的东西,并更好地理解它是如何工作的。

Yes i know that there are libraries that i can use to do this, but i wanted to build something of my own from the ground up and get a better understand of how it works.

MySocket.h

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

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

编辑:一切都运行良好,直到调用发送数据。

Everything runs well until the call to send data.

是否有一些小而重要的东西,为了让这个工作我不见了?
或者我错过了大局?

Is there something small but critical in order for this to work that i'm missing? Or i'm missing the big picture?

任何帮助或指南都表示赞赏。
提前致谢,祝周末愉快

Any help or guide is appreciated. Thanks in advance and have a nice weekend

推荐答案

删除SetAdress,一切正常。我现在已经测试了这个;

remove SetAdress and all will be work fine. i've tested this now;

这篇关于在IOS上使用CFSocket进行UDP广播的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆