5

このテーマについていくつかのグーグル検索といくつかの読書を行ってきましたが、検索にどれだけの時間を費やしても正しく理解できないようです.

私がやりたいことは、ネットワークに接続されているデバイスが提供するサービスへの関心を宣伝することによって、デバイスのブロードキャスト メッセージを受信することです。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

編集:データを送信するための呼び出しまで、すべてがうまくいきます。

これが機能するために、私が見逃している小さいながらも重要なものはありますか? それとも私は全体像を見逃していますか?

ヘルプやガイドをいただければ幸いです。前もって感謝し、良い週末を

4

2 に答える 2

1

SetAdress を削除すると、すべて正常に動作します。私は今これをテストしました;

于 2014-02-04T20:11:54.300 に答える
0

この初期化をアドレスで使用するのはどうですか

CFDataRef address=CFDataCreate(kCFAllocatorDefault,(UInt8 *)&addr,sizeof(addr));
于 2013-07-03T10:03:36.360 に答える