iPhone上的SSDP
题
我需要能够发送一条UDP消息,还需要收到一条消息,以便从iPhone上发现网络上的SSDP设备。
我知道我需要将数据包发送到多播地址,而我的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使用Internet插座的网络编程指南:
谢谢
戴夫
PS
在这种情况下,我无法使用任何第三方库和框架。
解决方案 3
好的,终于做到了。在公共领域(感谢Chris)中找到了一个名为asyncudpsocket的课程,该课程使您可以创建一个UDP插座,然后可以打开广播并加入多播地址。
有一个不错的senddata方法,并添加到运行循环中以防止阻塞。
希望有帮助。
戴夫
其他提示
我已经成功地使用了Asyncudpsocket来运行SSDP Discovery并查找控制器。这是我的代码片段:
初始化和设置套接字:
// AsyncUdpSocket *ssdpSock = [[AsyncUdpSocket alloc] initWithDelegate:self];
AsyncUdpSocket *ssdpSock = [[AsyncUdpSocket alloc] initIPv4];
[ssdpSock setDelegate:self];
请注意第一行评论。我在 异步论坛 重复的一些问题。我认为我不面对他们,但无论如何我都做到了。
我添加了错误检查,这很有用,因为在调试期间,我没有关闭插座,并且开始获得插座设置失败:
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,但是我在没有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.