max-age表示收到该消息后若干秒内没有收到该设备发出的任何通知消息,就认为该设备已经不存在网络上了;LOCATION表示该设备的描述文件,用于确定该设备包含哪些逻辑设备和哪些服务等等;USN表示Unique Service Name。
比如对于上面那条示例搜索消息,我的ADSL返回的响应是:
HTTP/1.1 200 OKCACHE-CONTROL:max-age=1800EXT:LOCATION:http://10.0.0.138:80/IGD.xmlSERVER:SpeedTouch 510 4.0.2.0.1 UPnP/1.0 (14E31Y7)ST:upnp:rootdeviceUSN:uuid:UPnP-SpeedTouch510-1_00-90-D0-7F-AD-37::upnp:rootdevice
3.接下来就是取得该设备的描述文件,用于确定该设备信息和所支持的功能。通过上面的响应信息的LOCATION属性,可以得到一个URL,可以通过HTTP请求该URL得到该设备的描述文件。注意,仅仅在搜索和通知的时候是基于UDP的,其余的都是基于TCP的。设备描述文件定义可在UPnP Device Architecture中找到,比较长就不贴了。
比如上面我的ADSL返回LOCATION是http://10.0.0.138:80/IGD.xml,访问该地址,返回的一个XML片断是:
<?xml version="1.0" ?> < root xmlns =" urn:schemas-upnp-org:device-1-0 "> < specVersion > < major > 1 </ major > < minor > 0 </ minor > </ specVersion > < URLBase > http://10.0.0.138 </ URLBase > < device > < deviceType > urn:schemas-upnp-org:device:InternetGatewayDevice:1 </ deviceType > < friendlyName > SpeedTouch 510 (14E31Y7) </ friendlyName > < manufacturer > THOMSON multimedia </ manufacturer > < manufacturerURL > http://www.thomson-multimedia.com </ manufacturerURL > < modelDescription > DSL Internet Gateway </ modelDescription > < modelName > SpeedTouch </ modelName > < modelNumber > 510 </ modelNumber > < modelURL > http://www.speedtouch.com </ modelURL > < serialNumber > 14E31Y7 </ serialNumber > < UDN > uuid:UPnP-SpeedTouch510-1_00-90-D0-7F-AD-37 </ UDN > < presentationURL > /index.htm </ presentationURL > < serviceList > < service > < serviceType > urn:schemas-upnp-org:service:Layer3Forwarding:1 </ serviceType > < serviceId > urn:upnp-org:serviceId:layer3f </ serviceId > < controlURL > /upnp/control/layer3f </ controlURL > < eventSubURL > /upnp/event/layer3f </ eventSubURL > < SCPDURL > /Layer3Forwarding.xml </ SCPDURL > </ service > </ serviceList > < deviceList > ...... </ deviceList > </ device > </ root > 在UPnP规范中规定,一个设备可以包含若干的嵌入设备和服务。比如对于最常用到的Internet Gateway Device中,UPnP InternetGatewayDevice模板中规定 可以看到在根设备中包含了Layer3 Forwarding Service和两个嵌入设备:WANDevice和LANDevice,而WANDevice下面又包含了若干WANConnectionDevice等等。 4.得到设备所提供的服务描述。在刚才的设备描述中有一个ServiceList节点,该节点下每个Service节点都包含一个 SCPDURL节点,这个就是服务描述文件所在的位置,比如上面我的ADSL中Layer3 Forwarding Service服务描述文件的位置就是/Layer3Forwarding.xml,再组合URLBase节点属性值http://10.0.0.138,即得到该服务描述文件URL为http://10.0.0.138/Layer3Forwarding.xml,该文件详细的描述了该服务所提供的操作列表以及相应的参数和参数范围。 5.调用服务所提供的操作。调用是通过发送相应SOAP消息到该服务的控制URL上来完成的。该信息在UPnP Device Architecture中是如下定义的: POST path of control URL HTTP/1.1HOST: host of control URL:port of control URLCONTENT-LENGTH: bytes in bodyCONTENT-TYPE: text/xml; charset="utf-8"SOAPACTION: "urn:schemas-upnp-org:service:serviceType:v#actionName"<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:actionName xmlns:u="urn:schemas-upnp-org:service:serviceType:v"> <argumentName>in arg value</argumentName> other in args and their values go here, if any </u:actionName> </s:Body></s:Envelope> 就用在IGD设备上增加端口映射这个操作来举例,将网关的5678端口映射到内网10.0.0.1的8765端口,该操作被发送的SOAP消息如下: POST /upnp/control/wanpppcpppoe HTTP/1.0CONTENT-TYPE: text/xml; charset="utf-8"HOST: 10.0.0.138:80CONTENT-LENGTH: 649SOAPACTION: "urn:schemas-upnp-org:service:WANPPPConnection:1#AddPortMapping" <?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:AddPortMapping xmlns:u="urn:schemas-upnp-org:service:WANPPPConnection:1"> <NewRemoteHost></NewRemoteHost> <NewExternalPort>5678</NewExternalPort> <NewProtocol>tcp</NewProtocol> <NewInternalPort>8765</NewInternalPort> <NewInternalClient>10.0.0.1</NewInternalClient> <NewEnabled></NewEnabled> <NewPortMappingDescription></NewPortMappingDescription> <NewLeaseDuration></NewLeaseDuration> </u:AddPortMapping> </s:Body></s:Envelope> 操作成功,设备的返回值是: HTTP/1.0 200 CONTENT-TYPE: text/xml; charset="utf-8"SERVER: SpeedTouch 510 4.0.2.0.1 UPnP/1.0 (14E31Y7)CONTENT-LENGTH: 304Connection: closeEXT: <?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <m:AddPortMappingResponse xmlns:m="urn:schemas-upnp-org:service:WANPPPConnection:1"></m:AddPortMappingResponse> </s:Body></s:Envelope> 6.在设备一些属性变化了的时候,如果Control Point订阅了它的事件通知,则它会发送相应的通知给Control Point。这部分我还未研究透彻,有待进一步了解。 这些只是一个基本的Control Point的流程,详细的部分可以访问 http://www.upnp.org/download/UPnPDA10_20000613.htm,看看UPnP Device Architecture,里面有详细的描述。 大部分程序员对UPnP的兴趣只限于动态映射IGD设备端口,因此可以去看看IGD设备规范,网址是 http://www.upnp.org/standardizeddcps/igd.asp 在Window下实现动态端口映射,要做的完美一点,最好是按照前面一篇文章说的步骤,首先检测Window下ICF是否打开,打开的话就得调用ICF的API在防火墙上打开相应的端口,要不多播信息这些都被防火墙拦截下来了,也就没有办法找到UPnP设备了。不少非微软的应用都没有注意这一点,让我在初步了解UPnP技术的时候郁闷了半天,以为Windows 2003取消了对UPnP的支持就没有办法在Windows 2003下使用UPnP设备了,最后才发现是防火墙惹得祸。 因此Windows支不支持UPnP没有关系,如果不支持也只是限于没有办法调用微软提供的API而已:)