首页 文章

在Objective C中解析SSDP Discovery的最佳方法

提问于
浏览
2

我正在开发一个非常简单的应用程序来发现使用SSDP的设备,我正在尝试找到解析此命令响应的最简单方法 . 我试图避免必须做一堆NSString或正则表达式操作 .

我尝试了以下两种方法:

Approach 1: 使用GCDAsyncUdpSocket,我能够成功发送发现命令并获得以下响应:


HTTP / 1.1 200好的
缓存控制:max-age = 300
ST:roku:ecp
USN:uuid:roku:ecp:1234567890
分机:
服务器:Roku UPnP / 1.0 MiniUPnPd / 1.4
地点:http://192.168.XX.XX:8060/


这看起来像是一个常规的HTTP响应,但是使用GCDAsyncUdpSocket,我得到的响应是一个NSData对象,我可以很容易地将其转换为NSString . 然而,理想的是以某种方式将其转换为NSHTTPURLResponse然后使用其方法来获取字段值 . 不知道是否可以这样做?

Approach 2: 我尝试使用常规NSURLRequest尝试发送此命令,然后我就可以获得NSHTTPURLResponse了 . 但是,我继续收到错误,因为SSDP发现命令要求我将此请求发送到端口1900.我使用以下代码发送"HTTP"请求,我知道它不是严格的HTTP,但我认为它可能更容易发送此UDP命令的方式,因为要求看起来非常类似于HTTP .

NSURL *url = [NSURL URLWithString:@"http://239.255.255.250:1900"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
                            cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];


[request setHTTPMethod:@"M-SEARCH *"];
[request setValue:@"239.255.255.250:1900" forHTTPHeaderField:@"Host"];
[request setValue:@"\"ssdp:discover\"" forHTTPHeaderField:@"Man"];
[request setValue:@"roku:ecp" forHTTPHeaderField:@"ST"];

NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:YES];
    if (connection)
    {
        NSLog(@"Connection success!");
    }
    else
    {
        NSLog(@"Connection failed!");   
    }

当我这样做,连接成功,但我在NSURLConnection的didFailWithError委托中收到以下错误:

失败错误域= NSPOSIXErrorDomain代码= 47“操作无法完成 . 协议族不支持的地址族”UserInfo = 0x8875940 {NSErrorFailingURLKey = http://239.255.255.250:1900 /,NSErrorFailingURLStringKey = http://239.255 . 255.250:1900 /}

只有当我使用端口1900时才会出现此错误,如果我将其删除或使用其他更多HTTP友好端口(如8080),那么这可行,但显然我尝试发现的设备没有正确响应,除非它在端口获取请求1900 .

感谢您的任何帮助,您可以提供 .

1 回答

  • 3

    端口1900固定为SSDP . 修复所有UPnP设备以侦听此端口,并且连接节点期望这样 . 您可以将't change it. It'作为UPnP设计目标的一部分"work out of the box" . 此外,我的Cocoa专业知识非常有限,但我认为 NSHTTPURLResponse 不会让事情变得简单 . [NSHTTPURLResponse allHeaderFields] 返回 NSDictionary ,这意味着您不再知道 Headers 字段的原始顺序是什么 . 你需要知道 Ext: 之后会发生什么,这是一个元头 .

    我建议自己解析响应,这不应该比一个循环复杂得多,用行分隔响应然后按 : 分割 . 或者,不要尝试滚动自己的SSDP握手,而是使用现成的Cocoish库,如Upnpx,Cyberlink或Platinum . 对于发现阶段,它可能感觉像是不合适的重型火炮,但是我想知道除了实际尝试在设备上调用某些动作之外你还会对设备做什么 .

相关问题