سؤال

يجب أن أكون قادرًا على إرسال رسالة UDP وأيضًا تلقي رسالة لاكتشاف أجهزة SSDP على الشبكة من iPhone.

أعلم أنني بحاجة إلى إرسال الحزمة إلى عنوان البث المتعدد وأن طلب HTTP الخاص بي يحتاج إلى أن يبدو مثل هذا:

M-SEARCH * HTTP/1.1
Host: 239.255.255.250:1900
Man: ssdp:discover
Mx: 3
ST: "urn:schemas-upnp-org:device:InternetGatewayDevice:1"

من قراءة المستندات ، يبدو أنه يمكنني القيام بكل هذا باستخدام CFNetwork وعلى الرغم من القراءة (وإعادة قراءة المستندات) ، فإنني أكافح من أجل البدء. هل يمكن لأي شخص أن يوصي والدروس التعليمية أو قصاصات التعليمات البرمجية لإحضارني على سنام التعلم الأولي؟

لقد حصلت على دليل برمجة CFNetwork:

http://developer.apple.com/mac/library/documentation/networking/conceptual/cfnetwork/cfnetwork.pdf

ودليل Beej لبرمجة الشبكة باستخدام مآخذ الإنترنت:

http://beej.us/guide/bgnet/

شكرًا

ديف

ملاحظة

أنا غير قادر على استخدام أي من المكتبات والأطر من الطرف الثالث في هذه الحالة.

هل كانت مفيدة؟

المحلول 3

حسنًا ، فعل ذلك أخيرًا. وجدت فصلًا في المجال العام (بفضل كريس) يسمى Asyncudpsocket والذي يتيح لك إنشاء مقبس UDP يمكنك تشغيله بعد ذلك للبث والانضمام إلى عنوان البث المتعدد.

هناك طريقة SendData لطيفة ، مع إضافة إلى حلقة تشغيل لمنع الحظر.

امل ان يساعد.

ديف

نصائح أخرى

لقد استخدمت Asyncudpsocket بنجاح لتشغيل SSDP Discovery والعثور على وحدات التحكم. فيما يلي قصاصات الكود الخاصة بي:

تهيئة وإعداد المقبس:

//  AsyncUdpSocket *ssdpSock = [[AsyncUdpSocket alloc] initWithDelegate:self];
    AsyncUdpSocket *ssdpSock = [[AsyncUdpSocket alloc] initIPv4];
    [ssdpSock setDelegate:self];

لاحظ أن السطر الأول علق. لقد وجدت على منتديات Asyncudpsocket بعض القضايا مع التكرارات. لا أعتقد أنني كنت أواجههم ولكني فعلت ذلك على أي حال.

أضفت التحقق من الأخطاء ، وكان ذلك مفيدًا لأنه أثناء تصحيح الأخطاء لم أكن أغلق مآخذ وبدأت في الحصول على فشل إعداد المقبس:

NSError *socketError = nil;

    if (![ssdpSock bindToPort:1900 error:&socketError]) {
        NSLog(@"Failed binding socket: %@", [socketError localizedDescription]);
        return statusController;
    }

    if(![ssdpSock joinMulticastGroup:@"239.255.255.250" error:&socketError]){
        NSLog(@"Failed joining multicast group: %@", [socketError localizedDescription]);
        return statusController;
    }

    if (![ssdpSock enableBroadcast:TRUE error:&socketError]){
        NSLog(@"Failed enabling broadcast: %@", [socketError localizedDescription]);
        return statusController;
    }

    [ssdpSock sendData:[self.discoverControllerString dataUsingEncoding:NSUTF8StringEncoding]
                toHost:@"239.255.255.250"
                  port:1900
           withTimeout:2
                   tag:1];

لاحظ التغييرات التي أجريتها حتى وقت الخروج. ثم أخيراً قام بإعداد استلام ، وأغلق المقبس. لاحظ إغلاق المقبس. بما أنني في صفي الخاص عندما أقوم بتشغيل هذا - فإن الكود أعلاه لم ينجح بالنسبة لي.

[ssdpSock receiveWithTimeout: 2 tag:1];
    [NSTimer scheduledTimerWithTimeInterval: 5 target: self 
                                   selector:@selector(completeSearch:) userInfo: self repeats: NO]; 





    [ssdpSock closeAfterSendingAndReceiving];

من المحتمل أن يكون التغيير الأكثر أهمية هو العودة "لا" إذا لم أجد وحدة التحكم الخاصة بي. أول استلام كان بالمناسبة رسالة الاكتشاف نفسها تعود. وعندما قرأت من خلال ملف asyncudpsocket.h بعناية - إرجاع "لا" عندما لا تكون حزمة تبحث عنها.

لاحظ أيضًا أنني أستخدم ARC في الكود الخاص بي ، لكنني قمت بتجميع Asyncudpsocket دون دعم ARC.

-(void) completeSearch: (NSTimer *)t 
{

    NSLog(@"%s",__FUNCTION__);

    //[ssdpSock close];
    //ssdpSock = nil;

}


- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock 
     didReceiveData:(NSData *)data 
            withTag:(long)tag 
           fromHost:(NSString *)host 
               port:(UInt16)port
{
    NSLog(@"%s %ld %@ %d",__FUNCTION__,tag,host,port);
    NSString *aStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];

    NSLog(@"%@",aStr);



    NSString *compareString = [aStr stringByPaddingToLength:[self.responseString length] withString:@"." startingAtIndex:0];
    //NSLog(@"%@", compareString);
    //NSLog(@"%@", self.responseString);

    if ([compareString isEqualToString:self.responseString])
    {
        NSLog(@"String Compare, Controller Found!");
        [self.controllerList addObject:aStr];
        //NSData *controllerIP = [aStr dataUsingEncoding:NSUTF8StringEncoding];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"DiscoveredController" object:nil];


        return YES;
    }

    return NO;

}

لدي الرمز التالي لبحث SSDP في تطبيقي:

-(void)discoverDevices {
ssdpSock = [[AsyncUdpSocket alloc] initWithDelegate:self];
[ssdpSock enableBroadcast:TRUE error:nil];
NSString *str = @"M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMan: \"ssdp:discover\"\r\nST: mydev\r\n\r\n";    
[ssdpSock bindToPort:0 error:nil];
[ssdpSock joinMulticastGroup:@"239.255.255.250" error:nil];
[ssdpSock sendData:[str dataUsingEncoding:NSUTF8StringEncoding] 
         toHost: @"239.255.255.250" port: 1900 withTimeout:-1 tag:1];
[ssdpSock receiveWithTimeout: -1 tag:1];
[NSTimer scheduledTimerWithTimeInterval: 5 target: self 
           selector:@selector(completeSearch:) userInfo: self repeats: NO]; }


-(void) completeSearch: (NSTimer *)t {
NSLog(@"%s",__FUNCTION__);
[ssdpSock close];
ssdpSock = nil;}

- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{
NSLog(@"%s %d %@ %d",__FUNCTION__,tag,host,port);
NSString *aStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(@"%@",aStr);}

يستخدم AsyncUdpSocket من cocoaasyncsocket.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top