SSDP на iPhone
Вопрос
Мне нужно иметь возможность отправлять сообщение 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 и, несмотря на чтение (и повторно прочитать документы), я борюсь, чтобы начать работу. Может кто-нибудь рекомендовать и учебники или кодовые фрагменты, чтобы заставить меня на первоначальное обучение Hump?
У меня есть руководство по программированию CFNetWork:
http://developer.apple.com/mac/library/documentation/networking/coneptual/cfnetwork/cfnetwork.pdf.
и руководство Beej к сетевой программированию с использованием интернет-розеток:
Спасибо
Дейв
PS.
Я не могу использовать любую из 3-го библиотек и структур 3-го вечеринок в этом случае.
Решение 3
Хорошо, наконец сделали это. Нашел класс в общественном домене (спасибо CHRIS), называемый asyncudposeSocket, который позволяет создать разъем UDP, который вы можете включить вещание и присоединиться к многоадресному адресу.
Существует хороший метод Senddata, в комплекте с добавлением в цикл прогона для предотвращения блокировки.
Надеюсь, это поможет.
Дейв
Другие советы
Я успешно использовал Asyncudpsocket для запуска SSDP Discovery и найти контроллеров. Вот мои кодовые фрагменты:
Инициализировать и установить розетку:
// AsyncUdpSocket *ssdpSock = [[AsyncUdpSocket alloc] initWithDelegate:self];
AsyncUdpSocket *ssdpSock = [[AsyncUdpSocket alloc] initIPv4];
[ssdpSock setDelegate:self];
Обратите внимание, что первая строка прокомментирована. Я нашел на AsyncudposeSocket Forums некоторые проблемы с дубликатами. Я не думаю, что я сталкивался с ними, но я таксил так.
Я добавил проверку ошибок, и это было полезно, потому что во время моей отладки я не закрывал розетки, и я начал получать сбои набора сокетов:
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];
Самое важное изменение, вероятно, возвращалось «нет», если я не нашел мою контроллер. Первый прием был кстати, это сообщение о открытии сам по себе возвращается. И когда я прочитал через файл asyncudposeS.h тщательно - возвращая «нет», когда он не пакет, который вы ищете помощи.
Также обратите внимание, что я использую дугу в моем коде, но я составил AsyncudposeSocket без поддержки дуги.
-(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..