IM通讯协议总结之三SIMPLE协议

Posted kevin_baixy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IM通讯协议总结之三SIMPLE协议相关的知识,希望对你有一定的参考价值。

2.SIMPLE协议

SIMPLE(SIP Instant Messaging and Presence LeveragingExtensions)是SIP的扩展协议,其资料找到一篇中文的文档及一篇RFC3428文档,中文的文档主要讲是对SIMPLE协议的presence介绍,FC3428主要讲对SIP扩展的即时通讯的介绍。

通过查找资料得知应用此协议的软件:原MSN版本4(现已无法使用),无法抓取SIMPLE协议的数据包;外国软件Bria,可以使用,但只能抓取打电话的SIP协议数据包,其它通讯聊天及视频会议的情景需要付费才能使用,因此也未抓取到数据包。

下面从Presence与InstantMessage两个模块介绍SIMPLE协议。

2.1.基于 SIMPLE 协议的Presence 介绍

“presence”,也作“presenceinformation”,中文一般译为“呈现”,用以传达某一用户通过一组设备进行通信的能力和意愿。拿常见的MSN Messenger来举例,MSN v7.5为用户提供的可选状态有:联机、忙碌、马上回来、离开、接听电话、外出就餐和显示为脱机。这些状态便称为“presence 状态”,它们表征了用户当前处于的某种状态和用户进行通信的意愿。同时,这些状态还反映出与该用户进行通信的能力,比如若用户处于“脱机”状态的话,别的用户便不能用即时消息与之通信。因此,一个最简单的presence过程如下:一个用户(称为watcher)订阅(SUBSCRIBE)他感兴趣的另一用户(presentity)的presence状态,presentity接受订阅请求。以后presentity的状态发生变化之后他会发布(PUBLISH)自己的新状态,这个新状态会通知(NOTIFY)给watcher。(注:watcher、presentity等概念严格上来说指网络中的通信实体,这里为了解释方便将他们进行了扩展,也泛指人)

2.1.1基于 SIMPLE 协议的 presence 体系结构

SIMPLE 符合 RFC2778 提出的 presence 模型,其结构图如下:


各实体功能如下:

Presence Service:接收、存储和分发presence information。Presence Service既可以是一个物理实体上的server,也可以只是presentity和watcher之间的直接通信。在具体实现中前者比较常见,后者是P2P的模式。

Presentity:用于提供presence information给Presence Service。

Watcher:向Presence Service请求获取Presentity的presence information或自身的watcher information。

Principal:指单个的人、程序或者设备,也可以是人、程序、设备的集合体。对于Presence Service 来说,各个Principal是不同的。

Presence User Agent:为Principal提供手段来操作0个或者多个Presentity,Principal操作Presence User Agent改变Presentity的状态。是Principal和Presentity交互的interface。

Watcher User Agent:类似Presence User Agent,Principal通过其来操作0个或多个Watcher,Watcher收到Presentity的新状态之后也通过Watcher User Agent呈现给Principal。

Presence Protocol:定义了Presentity和Presence Service,Watcher和Presence Service之间交换消息的一组标准。

2.1.2消息流程

情景设定:

假设本 presence 系统的域名是“cintel.net.cn”,系统中有一下几个实体:

 

Presence Server:系统中的presence服务器。负责接收和处理所辖域内用户的 订阅、发布状态请求;通知用户其订阅的状态信息发生改变;处理添加和删除好友;处理添加和删除黑白名单;管理维护所辖域内用户数据等。其 SIP-URI 为“sip:ps.cintel.net.cn”,FQDN为“ ps.cintel.net.cn”

 

A:代表用户A。在网络中是一个终端(可以是软终端或者硬终端),集watcher和presentity实体功能于一身。用于向Presence Server发送订阅(SUBSCRIBE)别的用户状态的请求;自己状态发生变化时向PresenceServer发布(PUBLISH)新的状态;接收和处理Presence Server发来的状态通知(NOTIFY);利用XCAP协议发送和接收添加删除好友、黑白名单的请求和响应等。其在系统中的AOR为“sip:A@ps.cintel.net.cn”,FQDN为“ a.cintel.net.cn”。

 

B:与A类似,AOR为“sip:B@ps.cintel.net.cn”,FQDN为“b.cintel.net.cn”。

C:与A类似,AOR为“sip:C@ps.cintel.net.cn”,FQDN为“c.cintel.net.cn”。

由于pidf只定义了基本的状态,如basic元素中的“open”和“close”两种状态(前者表示当前的通信状态可用(最常见的就是表示可以发送即时消息),后者表示当前的通信状态不可用),详细一点的状态信息比如“busy”、“away”等没有明确规定。要表示这种状态由具体实现决定,一般都是进行扩展,如teltel是在note元素中表达这种信息。另外,rpidf对pidf进行了扩展,提供丰富的各种信息。此文档中在PIDF的“status”元素下扩展“im”元素,来表示具体的状态(假设有“联机”、“忙碌”、“离开”和“显示为脱机”四种状态,对应的im元素值分别为“online”、“busy”、“away”

 

2.1.2.1订阅好友列表

2.1.2.1.1情景说明

A拥有且仅拥有B和C两位好友,也就是说A有权订阅B和C的状态信息。终端A启动,向Presence Server发送订阅其好友列表的请求(好友列表URI格式为“sip:username-list@ps.cintel.net.cn”)。假设B一开始处于不在线状态,C至始至终处于“open”状态。PresenceServer经过验证将B和C的状态信息通知A。一段时间后B登陆,其状态发生了变化,于是B向Presence Server发布其新状态。Presence Server处理之后将B的新状态通知A,A处理之后会正确显示出B的新状态。在每次订阅超时之前A会重新发送一个订阅请求刷新他的订阅。A退出,向Presence Server发送取消订阅的请求,Presence Server接收并发送最后一次状态通知。

2.1.2.1.2 SIP消息流程图


2.1.2.1.3消息流说明

1、A 启动,向Presence Server发送订阅其好友列表状态的请求。

M1消息如下:

SUBSCRIBE[D1]  sip:A-list@ps.cintel.net.cn[D2] SIP/2.0[D3] 
Via[D4] :SIP/2.0/UDP[D5] a.cintel.net.cn[D6] ; branch=z9hG4bKwYb6QREiCL
Max-Forwards:70[D7] 
To: <sip:A-list@ps.cintel.net.cn >[D8] 
From:<sip:A@ps.cintel.net.cn>;[D9] tag=ie4hbb8t[D10] 
Call-ID:cdB34qLToC@a.cintel.net.cn[D11] 
CSeq: 1SUBSCRIBE[D12] 
Contact:<sip:a.cintel.net.cn>[D13] 
Event:presence[D14] 
Expires:3600[D15] 
Supported:eventlist[D16] 
Accept:application/pidf+xml
Accept: application/rlmi+xml

Accept: multipart/relate[D17] 
Content-Length:0[D18] 

 

2、向A发送“200 OK”,表明此次订阅已经得到 验证和授权,订阅操作成功。

M2消息如下:
SIP/2.0 200 OK
Via: SIP/2.0/UDP a.cintel.net.cn; branch=z9hG4bKwYb6QREiCL
To: < sip:A-list@ps.cintel.net.cn >;tag=zpNctbZq
From: <sip:A@ps.cintel.net.cn>;tag=ie4hbb8t
Call-ID: cdB34qLToC@a.cintel.net.cn
CSeq: 1 SUBSCRIBE
Contact: <sip:ps.cintel.net.cn>
Expires: 3200

Require:eventlist[D19] 
Content-Length: 0

 

3、根据RFC 3265的要求,Presence Server在返回一个针对SUBSCRIBE的200 OK响应之后会立即给A发送NOTIFY通知其已经知道的好友的状态。

 

M3 消息如下:

NOTIFY [D20] sip:a.cintel.net.cn SIP/2.0
Via: SIP/2.0/UDP ps.cintel.net.cn;branch=z9hG4bKMgRenTETmm
Max-Forwards: 70
From: <sip:A-list@ps.cintel.net.cn>;tag=zpNctbZq
To: <sip:A@ps.cintel.net.cn>;tag=ie4hbb8t
Call-ID: cdB34qLToC@a.cintel.net.cn
CSeq: 5768 NOTIFY

Contact:<sip:ps.cintel.net.cn>
Event: presence

Subscription-State[D21] : active;expires=3200
Require: eventlist
Content-Type: multipart/related;type="application/rlmi+xml";
start="<nXYxAE@ps.cintel.net.cn>";
boundary="50UBfW7LSCVLtggUPe5z"
Content-Length: 1560
--50UBfW7LSCVLtggUPe5z

Content-Transfer-Encoding:binary[D22] 
Content-ID: <nXYxAE@ ps.cintel.net.cn >
Content-Type:application/rlmi+xml;charset="UTF-8"[D23] 
<?xml version="1.0" encoding="UTF-8"?>
<list xmlns="urn:ietf:params:xml:ns:rlmi"
uri="sip:A-list@ps.cintel.net.cn"
version="1" fullState="true">
<name language="en">Buddy List of A</name>
<name language="de">Liste der Freunde of A</name>
<resource uri="sip:B@ps.cintel.net.cn">
<name>B</name>
<instance id="juwigmtboe" state="active"
cid="B@ps.cintel.net.cn"/>
</resource>
<resource uri="sip:C@ps.cintel.net.cn">
<name>C</name>
<instance id="hqzsuxtfyq" state="active"
cid="C@ps.cintel.net.cn"/>
</resource>
</list>
--50UBfW7LSCVLtggUPe5z
Content-Transfer-Encoding: binary
Content-ID: <B@ps.cintel.net.cn>
Content-Type: application/pidf+xml;charset="UTF-8"
<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
entity="sip:B@ps.cintel.net.cn">
<tuple id="sg89ae">
<status>
<basic>closed</basic>
<im>offline
[D24] </im>

</status>
</tuple>
</presence>
--50UBfW7LSCVLtggUPe5z
Content-Transfer-Encoding: binary
Content-ID: <C@ps.cintel.net.cn>
Content-Type: application/pidf+xml;charset="UTF-8"
<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
entity="sip:C@ps.cintel.net.cn">
<tuple id="slie74">
<status>
<basic>open</basic>
<im>online
[D25] </im>
</status>
<contactpriority="1.0">sip:C@ps.cintel.net.cn</contact>
</tuple>
</presence>
--50UBfW7LSCVLtggUPe5z—

 

4、A收到NOTIFY之后进行处理,将B和C的状态正确显示出来,并返回“200 OK”完成NOTIFY 事务。M4 消息如下:

SIP/2.0200 OK
Via: SIP/2.0/UDP ps.cintel.net.cn;branch=z9hG4bKMgRenTETmm
From: <sip:A-list@ps.cintel.net.cn>;tag=zpNctbZq
To: <sip:A@ps.cintel.net.cn>;tag=ie4hbb8t
Call-ID: cdB34qLToC@a.cintel.net.cn
CSeq: 5768 NOTIFY
Contact: <sip:a.cintel.net.cn>
Content-Length: 0

5、一段时间后B登陆,B向Presence Server发布其新的状态信息。类似于SUBSCRIBE方法, PUBLISH(PUBLISH不创建dialog)也要头字段Expires和Event。比较特殊的是PUBLISH中不包含Contact头字段。M5 消息如下:

PUBLISH [D26] sip:B@ps.cintel.net.cn SIP/2.0
Via: SIP/2.0/UDP b.cintel.net.cn;branch=z9hG4bK652hsge
Max-Forwards: 70
To: <sip:B@ps.cintel.net.cn>
From: <sip:B@ps.cintel.net.cn>;tag=1234wxyz
Call-ID:
81818181@b.cintel.net.cn

CSeq:1 PUBLISH
Expires: 3600
Event: presence
Content-Type: application/pidf+xml
Content-Length: 224
<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
entity="sip:B@ps.cintel.net.cn">
<tuple id="slie74">
<status>
<basic>open</basic>
<im>online</im>
</status>
</tuple>
</presence>

6、Presence Server收到PUBLISH请求之后将B的新状态保存在数据库中,并返回200响应。类似于SUBSCRIBE,也包含一个Expires头字段,用法也一 样。另外,此200响应中还应该有一个SIP-ETag 头字段,用来标识和验证B的下一次 PUBLISH。

M6消息如下:

 SIP/2.0 200 OK
Via: SIP/2.0/UDP b.cintel.net.cn;branch=z9hG4bK652hsge
To: <sip:B@ps.cintel.net.cn>;tag=1a2b3c4d
From: <sip:B@ps.cintel.net.cn>;tag=1234wxyz
Call-ID: 81818181@b.cintel.net.cn
CSeq: 1 PUBLISH
Expires: 3200

SIP-ETag:dx200xyz[D27] 
Content-Length: 0

7、Presence Server将B的新状态NOTIFY给A。此NOTIFY既可以包含全部好友的状态信息,也可以只包含状态发生变化的好友的状态信息,这里采用的 是后者。

M7消息如下:

 NOTIFY sip:a.cintel.net.cn SIP/2.0
Via: SIP/2.0/UDP ps.cintel.net.cn;branch=z9hG4bKMgRenTETmn
Max-Forwards: 70
From: <sip:A-list@ps.cintel.net.cn>;tag=zpNctbZq
To: <sip:A@ps.cintel.net.cn>;tag=ie4hbb8t
Call-ID: cdB34qLToC@a.cintel.net.cn
CSeq: 5769 NOTIFY
Contact: <sip:ps.cintel.net.cn>
Event: presence

Subscription-State:active;expires=2000
Require: eventlist
Content-Type: multipart/related;type="application/rlmi+xml";
start="<nXYxAF@ps.cintel.net.cn>";
boundary="60UBfW7LSCVLtggUPe5z"
Content-Length: 1560
--60UBfW7LSCVLtggUPe5z
Content-Transfer-Encoding: binary
Content-ID: <nXYxAF@ ps.cintel.net.cn >
Content-Type: application/rlmi+xml;charset="UTF-8"
<?xml version="1.0" encoding="UTF-8"?>
<list xmlns="urn:ietf:params:xml:ns:rlmi"
uri="sip:A-list@ps.cintel.net.cn"
version="2" fullState="false">
<name language="en">Buddy List of A</name>
<name language="de">Liste der Freunde of A</name>
<resource uri="sip:B@ps.cintel.net.cn">
<name>B</name>
<instance id="juwigmtbof" state="active"
cid="B@ps.cintel.net.cn"/>
</resource>
</list>
--60UBfW7LSCVLtggUPe5z
Content-Transfer-Encoding: binary
Content-ID: <B@ps.cintel.net.cn>
Content-Type: application/pidf+xml;charset="UTF-8"
<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
entity="sip:B@ps.cintel.net.cn">
<tuple id="sg89af">
<status>
<basic>open</basic>
<im>online</im>
</status>
</tuple>
</presence>
--60UBfW7LSCVLtggUPe5z

8、A收到NOTIFY之后将 B 的新状态显示出来,并返回 200 完成 NOTIFY 事 务。

M8 消息如下:

 SIP/2.0 200 OK
Via: SIP/2.0/UDP ps.cintel.net.cn;branch=z9hG4bKMgRenTETmn
From: <sip:A-list@ps.cintel.net.cn>;tag=zpNctbZq
To: <sip:A@ps.cintel.net.cn>;tag=ie4hbb8t
Call-ID: cdB34qLToC@a.cintel.net.cn
CSeq: 5769 NOTIFY
Contact: <sip:a.cintel.net.cn>
Content-Length: 0

9、一段时间之后, A 为了防止对好友列表的订阅超时而失效,再次发了一个带 Expires 头字段的 SUBSCRIBE,以刷新前一次订阅,注意这个SUBSCRIBE 仍要在前一个创建的对话(dialog)中。

M9 消息如下:

 SUBSCRIBE sip:A-list@ps.cintel.net.cn SIP/2.0
Via: SIP/2.0/UDP a.cintel.net.cn; branch=z9hG4bKwYb6QREiCM
Max-Forwards: 70
To: < sip:A-list@ps.cintel.net.cn >;tag=zpNctbZq
From: <sip:A@ps.cintel.net.cn>;tag=ie4hbb8t
Call-ID: cdB34qLToC@a.cintel.net.cn
CSeq: 2 SUBSCRIBE
Contact: <sip:a.cintel.net.cn>
Event: presence
Expires: 3600
Supported: eventlist
Accept: application/pidf+xml
Accept: application/rlmi+xml
Accept: multipart/related
Content-Length: 0

10、Presence Server收到SUBSCRIBE请求之后经判断得知是一个刷新订阅的请求,再次根据presence rules授权并选取适当的Expires值后返回给 A 一个 200 响应。

M10 消息如下:

 SIP/2.0 200 OK
Via: SIP/2.0/UDP a.cintel.net.cn; branch=z9hG4bKwYb6QREiCM
To: < sip:A-list@ps.cintel.net.cn >;tag=zpNctbZq
From: <sip:A@ps.cintel.net.cn>;tag=ie4hbb8t
Call-ID: cdB34qLToC@a.cintel.net.cn
CSeq: 2 SUBSCRIBE
Contact: <sip:ps.cintel.net.cn>
Expires: 3200

Require:eventlist
Content-Length: 0

11、 Presence Server 立即返回 NOTIFY 通知 A 当前其全部好友的 presence 状态。

M11 消息如下:
NOTIFYsip:a.cintel.net.cn SIP/2.0
Via: SIP/2.0/UDP ps.cintel.net.cn;branch=z9hG4bKMgRenTETmo
Max-Forwards: 70
From: <sip:A-list@ps.cintel.net.cn>;tag=zpNctbZq
To: <sip:A@ps.cintel.net.cn>;tag=ie4hbb8t
Call-ID: cdB34qLToC@a.cintel.net.cn
CSeq: 5770 NOTIFY
Contact: <sip:ps.cintel.net.cn>
Event: presence
Subscription-State: active;expires=3200
Require: eventlist
Content-Type: multipart/related;type="application/rlmi+xml";
start="<nXYxAG@ps.cintel.net.cn>";
boundary="70UBfW7LSCVLtggUPe5z"
Content-Length: 1560
--70UBfW7LSCVLtggUPe5z
Content-Transfer-Encoding: binary
Content-ID: <nXYxAG@ps.cintel.net.cn >
Content-Type: application/rlmi+xml;charset="UTF-8"
<?xml version="1.0" encoding="UTF-8"?>
<list xmlns="urn:ietf:params:xml:ns:rlmi"
uri="sip:A-list@ps.cintel.net.cn"
version="3" fullState="true">
<name language="en">Buddy List of A</name>
<name language="de">Liste der Freunde of A</name>
<resource uri="sip:B@ps.cintel.net.cn">
<name>B</name>
<instance id="juwigmtbog" state="active"
cid="B@ps.cintel.net.cn"/>
</resource>
<resource uri="sip:C@ps.cintel.net.cn">
<name>C</name>
<instance id="hqzsuxtfyh" state="active"
cid="C@ps.cintel.net.cn"/>
</resource>
</list>
--70UBfW7LSCVLtggUPe5z

Content-Transfer-Encoding:binary
Content-ID: <B@ps.cintel.net.cn>
Content-Type: application/pidf+xml;charset="UTF-8"
<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
entity="sip:B@ps.cintel.net.cn">
<tuple id="sg89ag">
<status>
<basic>open</basic>
<im>online</im>
</status>
</tuple>
</presence>
--70UBfW7LSCVLtggUPe5z
Content-Transfer-Encoding: binary
Content-ID: <C@ps.cintel.net.cn>
Content-Type: application/pidf+xml;charset="UTF-8"
<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
entity="sip:C@ps.cintel.net.cn">
<tuple id="slie76">
<status>
<basic>open</basic>
<im>online</im>
</status>
<contactpriority="1.0">sip:C@ps.cintel.net.cn</contact>
</tuple>
</presence>
--70UBfW7LSCVLtggUPe5z—

12、A 收到 NOTIFY 消息之后刷新所有好友的 presence 状态并返回 200 响应完成 NOTIFY 事务。

 M12 消息如下:

 SIP/2.0 200 OK
Via: SIP/2.0/UDP ps.cintel.net.cn;branch=z9hG4bKMgRenTETmo
From: <sip:A-list@ps.cintel.net.cn>;tag=zpNctbZq
To: <sip:A@ps.cintel.net.cn>;tag=ie4hbb8t
Call-ID: cdB34qLToC@a.cintel.net.cn
CSeq: 5770 NOTIFY
Contact: <sip:a.cintel.net.cn>
Content-Length: 0

 

13、 后来, A 终端退出,会触发一个取消订阅的请求,在 SIMPLE 中这是通过置 Expires 头字段值为 0 来完成的。此 SUBSCRIBE 仍属于第一个创建的对话 (dialog)。

 M13 消息如下:

 SUBSCRIBE sip:A-list@ps.cintel.net.cn SIP/2.0
Via: SIP/2.0/UDP a.cintel.net.cn; branch=z9hG4bKwYb6QREiCN
Max-Forwards: 70
To: < sip:A-list@ps.cintel.net.cn >;tag=zpNctbZq
From: <sip:A@ps.cintel.net.cn>;tag=ie4hbb8t
Call-ID: cdB34qLToC@a.cintel.net.cn
CSeq: 3 SUBSCRIBE
Contact: <sip:a.cintel.net.cn>
Event: presence
Expires: 0
Supported: eventlist
Accept: application/pidf+xml
Accept: application/rlmi+xml
Accept: multipart/related
Content-Length: 0

14、Presence Server 接受取消订阅的请求,向A返回Expires值为 0 的 200 响应。

M14 消息如下:

SIP/2.0200 OK
Via: SIP/2.0/UDP a.cintel.net.cn; branch=z9hG4bKwYb6QREiCN
To: < sip:A-list@ps.cintel.net.cn >;tag=zpNctbZq
From: <sip:A@ps.cintel.net.cn>;tag=ie4hbb8t
Call-ID: cdB34qLToC@a.cintel.net.cn
CSeq: 3 SUBSCRIBE
Contact: <sip:ps.cintel.net.cn>
Expires: 0
Require: eventlist
Content-Length: 0

15、Presence Server 会给 A 发最后一次 NOTIFY,通知其所有好友的状态,并且 Subscription-State 的 expires 参数值设为 0,表示订阅有效时间已经结束,这 是最后一次 presence 状态发布。

M15 消息如下:
NOTIFYsip:a.cintel.net.cn SIP/2.0
Via: SIP/2.0/UDP ps.cintel.net.cn;branch=z9hG4bKMgRenTETmp
Max-Forwards: 70
From: <sip:A-list@ps.cintel.net.cn>;tag=zpNctbZq
To: <sip:A@ps.cintel.net.cn>;tag=ie4hbb8t
Call-ID: cdB34qLToC@a.cintel.net.cn
CSeq: 5771 NOTIFY
Contact:
sip:ps.cintel.net.cn

Event:presence
Subscription-State: active;expires=0
Require: eventlist
Content-Type: multipart/related;type="application/rlmi+xml";
start="<nXYxAH@ps.cintel.net.cn>";
boundary="80UBfW7LSCVLtggUPe5z"
Content-Length: 1560
--80UBfW7LSCVLtggUPe5z
Content-Transfer-Encoding: binary
Content-ID: <nXYxAH@ps.cintel.net.cn >
Content-Type: application/rlmi+xml;charset="UTF-8"
<?xml version="1.0" encoding="UTF-8"?>
<list xmlns="urn:ietf:params:xml:ns:rlmi"
uri="sip:A-list@ps.cintel.net.cn"
version="4" fullState="true">
<name language="en">Buddy List of A</name>
<name language="de">Liste der Freunde of A</name>
<resource uri="sip:B@ps.cintel.net.cn">
<name>B</name>
<instance id="juwigmtboh" state="active"
cid="B@ps.cintel.net.cn"/>
</resource>
<resource uri="sip:C@ps.cintel.net.cn">
<name>C</name>
<instance id="hqzsuxtfyi" state="active"
cid="C@ps.cintel.net.cn"/>
</resource>
</list>
--80UBfW7LSCVLtggUPe5z
Content-Transfer-Encoding: binary
Content-ID: <B@ps.cintel.net.cn>
Content-Type: application/pidf+xml;charset="UTF-8"
<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
entity="sip:B@ps.cintel.net.cn">
<tuple id="sg89ah">
<status>
<basic>open</basic>
<im>online</im>
</status>

</tuple>
</presence>
--80UBfW7LSCVLtggUPe5z
Content-Transfer-Encoding: binary
Content-ID: <C@ps.cintel.net.cn>
Content-Type: application/pidf+xml;charset="UTF-8"
<?xml version="1.0" encoding="UTF-8"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
entity="sip:C@ps.cintel.net.cn">
<tuple id="slie77">
<status>
<basic>open</basic>
<im>online</im>
</status>
<contact priority="1.0">sip:C@ps.cintel.net.cn</contact>
</tuple>
</presence>
--80UBfW7LSCVLtggUPe5z—

16、 A 收到最后一个 NOTIFY 之后返回 200 完成 NOTIFY 事务。

M16 消息如下:
SIP/2.0 200 OK
Via: SIP/2.0/UDP ps.cintel.net.cn;branch=z9hG4bKMgRenTETmp
From: <sip:A-list@ps.cintel.net.cn>;tag=zpNctbZq
To: <sip:A@ps.cintel.net.cn>;tag=ie4hbb8t
Call-ID: cdB34qLToC@a.cintel.net.cn
CSeq: 5771 NOTIFY
Contact: <sip:a.cintel.net.cn>
Content-Length: 0

2.1.2.2订阅单个用户(添加好友)

2.1.2.2.1情景说明

A 想添加 B 为好友,向 B 发起一个订阅 presence 状态的请求。 B 在线,且接受 了 A 的请求。于是, A 成功将 B 加为好友并且能够观察 B 的 presence 状态信息。

2.1.2.2.2SIP消息流程图