SOAP
RPC实现方式;http、xml
简介
简单对象访问协议 , Simple Object Access Protocol, 是交换数据的一种协议规范,使用在计算机网络Web服务中,交换带结构信息 。通过HTTP/HTTPS传输,消息格式采用xml。
- SOAP封装(envelope),它定义了一个框架,描述消息中的内容是什么,是谁发送的,谁应当接受并处理它以及如何处理它们;
- SOAP编码规则(encoding rules),它定义了一种序列化的机制,用于表示应用程序需要使用的数据类型的实例;
- SOAP RPC表示(RPC representation),它定义了一个协定,用于表示远程过程调用和应答;
- SOAP绑定(binding),它定义了SOAP使用哪种协议交换信息。使用HTTP/TCP/UDP协议都可以。
语法规则
- SOAP消息必须用XML来编码
- SOAP消息必须使用SOAP Envelope命名空间
- SOAP消息必须使用SOAP Encoding命名空间
- SOAP消息不能包含DTD引用
- SOAP消息不能包含XML处理指令
语法结构
必需的 Envelope 元素,可把此 XML 文档标识为一条 SOAP 消息
可选的 Header 元素,包含头部信息
必需的 Body 元素,包含所有的调用和响应信息
可选的 Fault 元素,提供有关在处理此消息所发生错误的信息
SOAP 在默认的命名空间中定义了三个属性。这三个属性是:actor、 mustUnderstand 以及 encodingStyle。这些被定义在 SOAP 头部的属性可定义容器如何对 SOAP 消息进行处理。
-
mustUnderstand
可用于标识标题项对于要对其进行处理的接收者来说是强制的还是可选的 。
soap:mustUnderstand="0|1" -
actor
用于将 Header 元素寻址到一个特定的端点 。 soap:actor="URI"
-
encodingStyle
用于定义在文档中使用的数据类型。此属性可出现在任何 SOAP 元素中,并会被应用到元素的内容及元素的所有子元素上。 soap:encodingStyle="URI"
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Header>
<m:Trans xmlns:m="http://www.w3schools.com/transaction/"
soap:mustUnderstand="1"
soap:actor="http://www.w3schools.com/appml/">
234
</m:Trans>
</soap:Header>
<soap:Body>
<m:GetPrice xmlns:m="http://www.w3schools.com/prices">
<m:Item>Apples</m:Item>
</m:GetPrice>
</soap:Body>
</soap:Envelope>
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body>
<m:GetPriceResponse xmlns:m="http://www.w3schools.com/prices">
<m:Price>1.90</m:Price>
</m:GetPriceResponse>
</soap:Body>
</soap:Envelope>
错误元素
在一条 SOAP 消息中,Fault 元素只能出现一次。SOAP 的 Fault 元素拥有下列子元素:
子元素 | 描述 |
---|---|
<faultcode> | 供识别故障的代码 |
<faultstring> | 可供人阅读的有关故障的说明 |
<faultactor> | 有关是谁引发故障的信息 |
<detail> | 存留涉及 Body 元素的应用程序专用错误信息 |
错误代码
错误 | 描述 |
---|---|
VersionMismatch | SOAP Envelope 元素的无效命名空间被发现 |
MustUnderstand | Header 元素的一个直接子元素(带有设置为 "1" 的 mustUnderstand 属性)无法被理解。 |
Client | 消息被不正确地构成,或包含了不正确的信息。 |
Server | 服务器有问题,因此无法处理进行下去。 |
消息实例
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<req:echo xmlns:req="http://localhost:8080/wxyc/login.do">
<req:category>classifieds</req:category>
</req:echo>
</soapenv:Body>
</soapenv:Envelope>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
<soapenv:Header>
<wsa:ReplyTo>
<wsa:Address>
http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
</wsa:Address>
</wsa:ReplyTo>
<wsa:From>
<wsa:Address>http://localhost:8080/axis2/services/MyService</wsa:Address>
</wsa:From>
<wsa:MessageID>ECE5B3F187F29D28BC11433905662036</wsa:MessageID>
</soapenv:Header>
<soapenv:Body>
<req:echo xmlns:req="http://localhost:8080/axis2/services/MyService/">
<req:category>classifieds</req:category>
</req:echo>
</soapenv:Body>
</soapenv:Envelope>
请求
POST /InStock HTTP/1.1
Host: www.example.org
Content-Type: application/soap+xml; charset=utf-8
Content-Length: nnn
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="http://www.example.org/stock">
<m:GetStockPrice>
<m:StockName>IBM</m:StockName>
</m:GetStockPrice>
</soap:Body>
</soap:Envelope>
响应
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: nnn
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="http://www.example.org/stock">
<m:GetStockPriceResponse>
<m:Price>34.5</m:Price>
</m:GetStockPriceResponse>
</soap:Body>
</soap:Envelope>
SSDP
网络中控制点发现设备或设备告知自己存在的协议;HTTP、UDP、xml、多播
简介
简单服务发现协议,Simple Service Discover Protocol 。一种应用层协议,是构成通用即插即用(UPnP)技术的核心协议之一。
简单服务发现协议提供了在局部网络里面发现设备的机制。控制点(接受服务的客户端)可以通过使用简单服务发现协议,根据自己的需要查询在自己所在的局部网络里面提供特定服务的设备。设备(提供服务的服务器端)也可以通过使用简单服务发现协议,向自己所在的局部网络里面的控制点宣告它的存在。
实现
简单服务发现协议是在HTTPU和HTTPMU的基础上实现的协议。使用NOTIFY和M-SEARCH方法。
协议消息
- ssdp:discover
- ssdp:alive
- ssdp:byebye
按照协议的规定,当一个控制点(客户端)接入网络的时候,它可以向一个特定的多播地址的SSDP端口使用M-SEARCH方法发送ssdp:discover
消息。当设备监听到这个保留的多播地址上有控制点发送的消息的时候,设备会分析控制点请求的服务,如果自身提供了控制点请求的服务,设备将通过单播的方式直接响应控制点的请求。
类似的,当一个设备接入网络的时候,它应当向一个特定的多播地址的SSDP端口使用NOTIFY方法发送ssdp:alive
消息。控制点根据自己的策略,处理监听到的消息。考虑到设备可能在没有通知的情况下停止服务或者从网络上卸载,"ssdp:alive"消息必须在HTTP协议头CACHE-CONTROL里面指定超时值,设备必须在约定的超时值到达以前重发"ssdp:alive"消息。如果控制点在指定的超时值内没有再次收到设备发送的"ssdp:alive"消息,控制点将认为设备已经失效。
当一个设备计划从网络上卸载的时候,它也应当向一个特定的多播地址的SSDP端口使用NOTIFY方法发送ssdp:byebye
消息。但是,即使没有发送"ssdp:byebye"消息,控制点也会根据"ssdp:alive"消息指定的超时值,将超时并且没有再次收到的"ssdp:alive"消息对应的设备认为是失效的设备。
在IPv4环境,当需要使用多播方式传送相关消息的时候,SSDP一般使用多播地址239.255.255.250和UDP端口号1900。SSDP在IPv6环境下使用多播地址FF0X::C,这里的X根据scope的不同可以有不同的取值。
SSDP 协议的请求消息有两种类型,第一种是服务通知NOTIFY,设备和服务使用此类通知消息声明自己存在;第二种是查询请求M-SEARCH,协议客户端用此请求查询某种类型的设备和服务。
消息实例
查询消息
ssdp:discover
M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900 //必须是239.255.255.250:1900(IPv4)或FF0x::C(IPv6)
MAN: "ssdp:discover" // 设置协议查询的类型,必须是:ssdp:discover
MX:3 //设置设备响应最长等待时间,设备响应在0和这个值之间随机选择响应延迟的值
ST: 设置服务查询的目标
HTTP/1.1 200 OK
CACHE-CONTROL: max-age = 指定通知消息存活时间,如果超过此时间间隔,控制点可以认为设备不存在
DATE: 指定响应生成的时间
EXT: 向控制点确认MAN头域已经被设备理解
LOCATION: 包含根设备描述的URL地址
SERVER: 包含操作系统名,版本,产品名和产品版本信息
ST: 服务查询的目标
USN: 表示不同服务的统一服务名,它提供了一种标识出相同类型服务的能力。
ST 必须是下面的类型:
ssdp:all 搜索所有设备和服务
upnp:rootdevice 仅搜索网络中的根设备
uuid:device-UUID 查询UUID标识的设备
urn:schemas-upnp-org:device:device-Type:version 查询device-Type字段指定的设备类型,设备类型和版本 由UPNP组织定义。
urn:schemas-upnp-org:service:service-Type:version 查询service-Type字段指定的服务类型,服务类型和版本 由UPNP组织定义。
通知消息
-
ssdp:alive消息
在设备加入系统时,它采用多播传送方式发送发现消息,包括告知设备包含的根设备信息,所有嵌入设备以及它包含的服务 。
如果一个根设备有n个嵌入设备,m个嵌入服务,而且包含k个不同的服务类型,这将会发出3 + 2n + k次请求。这些广告消息像控制点描述了设备的所有信息。这些消息必须作为一系列一起发出,发送的顺序无关紧要,但是不能对单个消息进行刷新或取消的操作。选择一个适当的持续期是在最小化网络通讯和最大化设备状态及时更新之间求得一个平衡,相对较短的持续时间可以保证控制点在牺牲网络流量的前提下获得设备的当前状态;持续期越长可以大大减少设备刷新造成的网络流量。一般而言,设备制造商应该选择一个适当的持续时间值。
由于UDP协议是不可信的,设备应该发送多次设备发现消息。而且为了降低控制点无法收到设备或服务广告消息的可能性,设备应该定期发送它的广告消息
NOTIFY * HTTP/1.1 HOST: 239.255.255.250:1900 CACHE-CONTROL: max-age = seconds until advertisement expires LOCATION: URL for UPnP description for root device
NT: //Notification Type,NT头必须为服务的服务类型。
NTS: ssdp:alive //Notification Sub Type 通知消息的子类型
USN: //Unique Service Name 设备实例的标识符
对于根设备,存在三种发现消息:
| NT | USN |
| ------------------ | --------------------------------------- |
| 根设备的UUID | 根设备的UUID |
| 设备类型:设备版本 | 根设备的UUID,设备类型:设备版本 |
| upnp:rootdevice | 根设备的UUID,设备类型和upnp:rootdevice |
对于嵌入设备,存在两种发现消息:
| NT | USN |
| ------------------ | ---------------------------------- |
| 嵌入设备的UUID | 嵌入设备的UUID |
| 设备类型:设备版本 | 嵌入设备的UUID,设备类型和设备版本 |
对于每个服务:
| NT | USN |
| ------------------ | ---------------------------------- |
| 服务类型:服务版本 | 相关设备的UUID,服务类型和服务版本 |
- ssdp:byebye消息
在设备和它的服务将要从网络中卸载时,设备应该对于每个未超期的ssdp:alive消息多播方式传送ssdp:byebye消息。但如果设备突然从网络卸载,它可能来不及发出这个通知消息。因此,发现消息必须在CACHE-CONTROL包含超时值,如果不重新发出广告消息,发现消息最后超时并从控制点的缓存中除去。
```http
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
NT: search target
NTS: ssdp:byebye
USN: advertisement UUID
wirshark
-
显示过滤
udp.dstport == 1900
ssdp -
捕获过滤
udp port 1900
UPnP
简介
通用即插即用,Universal Plug and Play。该协议的目标是使家庭网络(数据共享、通信和娱乐)和公司网络中的各种设备能够相互无缝连接,并简化相关网络的实现。
UPnP通过定义和发布基于开放、因特网通讯网协议标准的UPnP设备控制协议来实现这一目标。
UPnP体系允许PC间的点对点连接、网际互连和无线设备。它是一种基于TCP/IP、UDP和HTTP的分布式、开放体系。
UPnP使得任意两个设备能在LAN控制设备的管理下相互通信。
应用场景
- 家庭智能设备互连
- 网络P2P应用
BitTorrent, eMule, IPFS, Ethereum。利用 UPnP 能自动的把它们侦听的端口号映射到公网地址上,这样,公网上的用户也能对当前的 NAT 内网主机直接发起连接。 - UPnP影音媒体服务器
UPnP影音媒体服务器存储和共享数字媒体,比如:图片、电影或是音乐。
组件架构
组件角色
-
设备 device
通常意义下的设备,一台UPnP设备可以是多个服务的载体或多个子设备的嵌套
-
服务 service
在UPnP网络中,最小的控制单元就是服务。服务描述的是指设备在不同情况下的动作和设备的状态。例如,时钟服务可以表述为时间变化值、当前的时间值以及设置时间和读取时间两个活动,通过这些动作,就可以控制服务。
-
控制点 control point
在UPnP网络中,控制点指的是可以发现并控制其他设备的控制设备。在UPnP网络中,设备可以和控制点合并,为同一台设备,同时具有设备的功能和控制点的功能,即可以作为设备提供服务,也可以作为控制点发现和控制其他设备。
实现条件
-
NAT 网关设备必须支持 UPnP 功能
需要扮演控制点(239.255.255.250:1900)的角色,控制点提供的是 SSDP 服务。
操作系统必须支持 UPnP 功能
应用程序必须支持 UPnP 功能
协议
协议栈
- SSDP Simple Service Discovery Protocol
- SOAP Simple Object Access Protocol
- GENA Generic Event Notification Architecture
工作流程
首先控制点和设备都先获取IP地址后才能进行下一步的工作;
控制点首先要寻找整个网络上的UPnP设备,同时网络上的设备也要宣告自身的存在;
控制点要取得设备的描述,包括这些设备提供什么样的服务;
控制点发出动作信息给设备;
控制点监听设备的状态,当状态改变时作出相应的处理动作;
寻址
通过DHCP或Auto-IP。
首先向 DHCP服务器发送DHCPDISCOVER消息,如果在指定的时间内,设备没有收到DHCPOFFERS回应消息,设备必须使用 Auto-IP完成IP地址的设置。使用Auto-IP时,设备在地址范围169.254/169.16范围中查找空闲的地址。在选中一个地址之后,设备测试此地址是否在使用。如果此地址被占用,则重复查找过程直到找到一个未被占用的地址,此过程的执行需要底层操作系统的支持,地址的选择过程应该是随机的以避免多个设备选择地址时发生多次冲突。为了测试选择的地址是否未被占用,设备必须使用地址解析协议(ARP)。一个ARP查询请求设置发送者的硬件地址为设备的硬件地址,发送者的IP地址为全0。设备应该侦听ARP查询响应,或者是否存在具有相同IP地址的ARP查询请求。如果发现,设备必须尝试新的地址。
使用Auto IP的设备必须定时检测DHCP服务器是否存在,这可以通过定时发送DHCPDISCOVER消息实现,如果接收到DHCPOFFERS回应消息,设备必须释放Auto IP分配的地址,此时设备必须取消所有的广告消息并重新发出新的。
一个设备可以使用UPnP之外的更高层的协议,这些协议将为设备使用友好的名称。在这种情况下,将这些友好的主机名解析为IP地址就很必要了,DNS通常是用来实现此功能的。使用此功能的设备可能要包含一个DNS客户端,而且支持动态的DNS注册,通过注册将它自己的名字加入到地址分布图中。
发现
给定一个IP地址,UPnP网络中的第一步是发现。当一个设备被加入到网络中,UPnP检测协议允许该设备向控制点广播自己的服务。类似地,当一个控制点加入到网络中的时候,它也能够搜索到网络中存在的、感兴趣的设备相关信息。这两种类型的基础交互是一种仅包含少量、重要相关设备信息或者它的某个服务。比如,类型、标识和指向更详细信息的链接。UPnP检测协议是基于简单服务发现协议(SSDP)的。
描述
UPnP网络的下一步是描述。当一个控制点检测到一个设备时,它对该设备仍然知之甚少。为了使控制点了解更多关于该设备的信息或者和设备进行交互,控制点必须从设备发出的检测信息中包含的URL获取更多的信息。某个设备的UPnP描述是XML的方式,包括品牌、厂商相关信息,如型号名和编号、序列号、厂商名、品牌相关URL等。描述还包括一个嵌入式设备和服务列表,以及控制、事件传递和存在相关的URL。对于每种设备,描述还包括一个命令或动作列表,包括响应何种服务,针对各种动作的参数;这些变量描述出运行时设备的状态信息,并通过它们的数据类型、范围和事件来进行描述。
控制
UPnP网络的下一步是控制。当一个控制点获取到设备描述信息之后,它就可以向该设备发送指令了。为了实现此,控制点发送一个合适的控制消息至服务相关控制URL(包含在设备描述中)。控制消息也是通过简单对象访问协议(SOAP)用XML来描述的。类似函数调用,服务通过返回动作相关的值来回应控制消息。动作的效果,如果有的话,会反应在用于刻画运行中服务的相关变量。
事件通知
下一步是事件通知。一个UPnP描述包括一组命令列表和刻画运行时状态信息的变量。服务在这些变量改变的时候进行更新,控制点可以进行订阅以获取相关改变。服务通过发送事件消息来发布更新。事件消息包括一个或多个状态信息变量以及它们的当前数值。这些消息也是采用XML的格式,用通用事件通知体系进行格式化。一个特殊的初始化消息会在控制点第一次订阅的时候发送,它包括服务相关的变量名及值。为了支持多个控制点并存的情形,事件通知被设计成对于所有的控制点都平行通知。因此,所有的订阅者同等地收到所有事件通知。
事件消息使用HTTP协议传送,事件详细定义在通用事件通知结构(GENA)协议中。
展示
最后一步是展示。如果设备带有展示URL,那么控制点可以通过它来获取设备展示信息,即在浏览器中加载URL,并允许用户来进行相关控制或查看操作。具体支持哪些操作则是由展示页面和设备完成的。
交互
设备告知
NOTIFY * HTTP/1.1
Host:239.255.255.250:1900
Cache-control:max-age=1800
Location:http://192.168.0.1:49152/des.xml
Nt:upnp:rootdevice
Nts:ssdp:alive
Usn:uuid:de5d6118-bfcb-918e-0000-00001eccef34::upnp:rootdevice
设备查询
M-SEARCH * HTTP/1.1
Host:239.255.255.250:1900
Man:"ssdp:discover"
Mx:5 // 1到5之间的一个值,表示最大的等待应答的秒数
ST:ssdp:rootdevice // Search Target,表示搜索的节点类型。
HTTP/1.1 200 OK
Cache-control:max-age=1800
Ext:
Location:http://192.168.0.1:2345/xx.xml
Server:Microsoft-Windows-NT/5.1UPnP/1.0 UPnP-Device-Host/1.0
ST:ST:urn:schemas-upnp-org:service:ContentDirectory:1
USN:uuid:60b2e186-b084-44af-ac09-1c64ea1bb364::urn:schemas-upnp-org:service:ContentDirectory:1
设备描述
<?xml version="1.0" encoding="utf-8"?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
<specVersion>
<major>1</major>
<minor>1</minor>
</specVersion>
<device>
<deviceType>urn:schemas-upnp-org:device:BinaryLight:1</deviceType>
<friendlyName>KitchenLights</friendlyName>
<manufacturer>OpenedHand</manufacturer>
<modelName>VirtualLight</modelName>
<UDN>uuid:cc93d8e6-6b8b-4f60-87ca-228c36b5b0e8</UDN>
<serviceList>
<service>
<serviceType>urn:schemas-upnp-org:service:SwitchPower:1</serviceType>
<serviceId>urn:upnp-org:serviceId:SwitchPower:1</serviceId>
<SCPDURL>/SwitchPower1.xml</SCPDURL>
<controlURL>/SwitchPower/Control</controlURL>
<eventSubURL>/SwitchPower/Event</eventSubURL>
</service>
</serviceList>
</device>
</root>
服务描述
<?xml version="1.0" encoding="utf-8"?>
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
<specVersion>
<major>1</major>
<minor>1</minor>
</specVersion>
<actionList>
<action>
<name>SetTarget</name>
<argumentList>
<argument>
<name>NewTargetValue</name>
<relatedStateVariable>Target</relatedStateVariable>
<direction>in</direction>
</argument>
</argumentList>
</action>
<action>
<name>GetTarget</name>
<argumentList>
<argument>
<name>RetTargetValue</name>
<relatedStateVariable>Target</relatedStateVariable>
<direction>out</direction>
</argument>
</argumentList>
</action>
<action>
<name>GetStatus</name>
<argumentList>
<argument>
<name>ResultStatus</name>
<relatedStateVariable>Status</relatedStateVariable>
<direction>out</direction>
</argument>
</argumentList>
</action>
</actionList>
<serviceStateTable>
<stateVariablesendEventsstateVariablesendEvents="no">
<name>Target</name>
<dataType>boolean</dataType>
<defaultValue>0</defaultValue>
</stateVariable>
<stateVariablesendEventsstateVariablesendEvents="yes">
<name>Status</name>
<dataType>boolean</dataType>
<defaultValue>0</defaultValue>
</stateVariable>
</serviceStateTable>
</scpd>
控制
POST /control/url HTTP/1.1
HOST: hostname:portNumber
CONTENT-TYPE: text/xml;charset="utf-8"
CONTENT-LENGTH: length ofbody
USER-AGENT: OS/versionUPnP/1.1 product/version
SOAPACTION:"urn:schemas-upnp-org:service:serviceType:v#actionName"
<?xml version="1.0"?>
<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>
</u:actionName>
</s:Body>
</s:Envelope>
HTTP/1.1 200 OK
CONTENT-TYPE: text/xml;charset="utf-8"
DATE: when response wasgenerated
SERVER: OS/version UPnP/1.1product/version
CONTENT-LENGTH: bytes inbody
<?xml version="1.0"?>
<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:actionNameResponse xmlns:u="urn:schemas-upnp-org:service:serviceType:v">
<argumentName>out arg value</argumentName>
</u:actionNameResponse>
</s:Body>
</s:Envelope>
事件订阅
SUBSCRIBE publisher_path HTTP/1.1
HOST: publisherhost:publisher port
USER-AGENT: OS/versionUPnP/1.1 product/version
CALLBACK: <deliveryURL> //CALLBACK的值是回调的URL
NT: upnp:event //表示订阅事件
HTTP/1.1 200 OK
DATE: when response was generated
SERVER: OS/version UPnP/1.1 product/version
SID: uuid:subscription-UUID //本订阅的标识符,通常使用UUID
CONTENT-LENGTH: 0
TIMEOUT: Second-1800 //这里的值表示本订阅的有效期。这意味着在超时前,必须续订
续订与退订
SUBSCRIBE publisher_path HTTP/1.1
HOST: publisher host:publisher port
SID: uuid:subscription UUID
UNSUBSCRIBE publisher_path HTTP/1.1
HOST: publisher host:publisher port
SID: uuid:subscription UUID
事件消息
NOTIFY delivery_path HTTP/1.1
HOST: delivery host:delivery port
CONTENT-TYPE: text/xml; charset="utf-8"
NT: upnp:event
NTS: upnp:propchange
SID: uuid:subscription-UUID
SEQ: event key
CONTENT-LENGTH: bytes in body
<?xml version="1.0"?>
<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0">
<e:property>
<variableName>new value</variableName>
</e:property>
</e:propertyset>
HTTP/1.1 200 OK //当订阅者收到消息之后,必须在30秒内发送确认。