转自:http://hi.baidu.com/nathan2007/blog/item/1ee3823422ebbdb6d1a2d376.html
以下分析基于Fetion 2006 beta 2.1.0.0,其SIP-C协议的版本是2.0。
前面列出了飞信的SIP-C协议支持的所有SIP Method以及Header Field,下面就两个用户间的聊天,即互相发送文本消息来看看飞信通过SIP-C协议的工作过程。
先看看RFC规定的SIP的建立会话的标准过程,在RFC3261中通过SIP建立会话的过程是这样子的:
atlanta.com . . . biloxi.com
. proxy proxy .
. .
Alice's . . . . . . . . . . . . . . . . . . . . Bob's
softphone SIP Phone
| | | |
| INVITE F1 | | |
|--------------->| INVITE F2 | |
| 100 Trying F3 |--------------->| INVITE F4 |
|<---------------| 100 Trying F5 |--------------->|
| |<-------------- | 180 Ringing F6 |
| | 180 Ringing F7 |<---------------|
| 180 Ringing F8 |<---------------| 200 OK F9 |
|<---------------| 200 OK F10 |<---------------|
| 200 OK F11 |<---------------| |
|<---------------| | |
| ACK F12 |
|------------------------------------------------->|
| Media Session |
|<================================================>|
| BYE F13 |
|<-------------------------------------------------|
| 200 OK F14 |
|------------------------------------------------->|
| |
上图中F1-F14分别是步骤的编号,而Medai Session过程在飞信中,就是文本聊天消息的传递过程了。在RFC3428中对标准SIP的扩展了一个Message方法,通过Message方法承载这种即时消息,这样,上图中的Media Session按RFC3428的规定,就是这样的:
| F1 MESSAGE | |
|--------------------> | F2 MESSAGE |
| | ----------------------->|
| | |
| | F3 200 OK |
| | <-----------------------|
| F4 200 OK | |
|<-------------------- | |
| | |
| | |
| | |
User 1 Proxy User 2
飞信是完全依照以上RFC的要求来实现这一过程来的。
下面来看飞信具体实现的聊天过程是怎么样的。假定有这么一个聊天过程是:飞信用户A(飞信号为123456789,飞信用TCP方式工作在111.111.111.111:1111)双击好友列表中的飞信用户B(飞信号为987654321,飞信用TCP方式工作在222.222.222.222:2222),这时聊天窗口弹出,用户A对B发出:"Hello!测试“,然后用户A关闭了聊天窗口,结束了这次即时消息对话过程。
我们看用户A这一端来看整个聊天过程中,用户A与服务器(SIP的Proxy Server)的交互过程是 (请对照上面RFC的SIP会话建立过程,另外,下面的红色字是表示数据的发送方向,蓝色字是全部的SIP消息,即TCP包的包体部分。):
第一步:111.111.111.111:1111 >>>>>>>> 221.130.45.203:8080
I fetion.com.cn SIP-C/2.0
F: 123456789
I: 16
Q: 1 I
T: sip:987654321@fetion.com.cn;p=1972
K: text/html-fragment
K: multiparty
L: 137
v=0
o=-0 0 IN 111.111.111.111:1111
s=session
c=IN IP4 111.111.111.111:1111
t=0 0
m=message 1111 sip sip:123456789@fetion.com.cn;p=xxxx
上面是发到服务器的第一条消息,是一个SIP协议的INVITE请求,发到飞信的服务器,服务器地址是221.130.45.203,端口8080,协议是TCP,上面的SIP消息就直接放在TCP的包中,UTF-8编码。
消息的第1是请求行,I=INVITE(这缩写的标准在哪里?我还没找到来依据),fetion.com.cn是请求对象(又没用标准的uri),"sIP-C/2.0"是当前的SIP-C协议版本。
第2行开始是消息头:"F"即From,标识从用户A(123456789)发出的请求(依然没用标准uri,应该是sip:123456789@xx.fetion.com.cn才对吧....);"I"即CallID,按标准的SIP的规定,这应该是一个随机产生的一个全局唯一的标识符,它应该在客户端和服务器整个交互的过程中保持不变,但在飞信的SIP-C协议中,这是一个序列号,第一次与8080端口建立连接发出第一个请求时,这个值为1,以后每次发出一个请求则加1;"Q"即CSeq,也就是Command Sequence,它由一个整数的序列号和一个SIP方法组成,SIP方法与这个消息的SIP方法相同,这个序列号在一个会话过程中每次加1,这样来标识SIP消息的顺序;"T"就是To啦,这里倒是用了标准uri的表示,"K"即Supported,表示客户端所支持扩展;"L"即Content-Length,就是消息体的长度。
从v=0开始的是消息体,用SDP(Session Description Protocol)描述的,根据RFC:
v= (protocol version),在目前飞信的INVITE中,固定的v=0
o= (owner/creator and session identifier). 在目前飞信的INVITE中,前面是固定的,后面是发起人(用户A)的IP地址和端口
s= (session name). 在目前飞信的INVITE中,固定的为s=session
c=* (connection information - not required if included in all media).在目前飞信的INVITE中,除后面的发起人(用户A)的IP地址和端口外,前面是固定的。
t= (time the session is active) 。在目前飞信的INVITE中,固定的为"t=0 0"
m= (media name and transport address)。在目前飞信的INVITE中,"1111"是发起人的TCP端口,后面的sip:xxxxxxxx,是发起人的uri。
第二步:111.111.111.111:1111 <<<<<<<< 221.130.45.203:8080
SIP-C/2.0 100 Trying
Q: 1 I
T: sip:987654321@fetion.com.cn;p=xxxx
I: 16
这是服务器回过来的对第一步的INVITE消息的一个RESPONSE,所以,I=16,Q=1 I。表示正在查找用户B。
第三步:111.111.111.111:1111 <<<<<<<< 221.130.45.203:8080
SIP-C/2.0 200 OK
Q: 1 I
K: text/html-fragment
K: multiparty
T: sip:123456789@fetion.com.cn;p=xxx
I: 16
L: 135
v=0
o=-0 0 IN 222.222.222.222:2222
s=session
c=IN IP4 222.222.222.222:2222
t=0 0
m=message 2222 sip sip:987654321@fetion.com.cn;p=xxx
这是服务器转过来的用户B对用户A的INVITE的回复,是:OK,其中222.222.222.222:2222是用户B的IP和端口。
第四步:111.111.111.111:1111 >>>>>>>> 221.130.45.203:8080
A fetion.com.cn SIP-C/2.0
I: 16
Q: 1 A
T: sip:987654321@fetion.com.cn;p=xxx
F: 123456789
接着,用户A发出ACK消息。
第五步:111.111.111.111:1111 >>>>>>>> 221.130.45.203:8080
M fetion.com.cn SIP-C/2.0
F: 123456789
I: 16
Q: 2 M
T: sip:987654321@fetion.com.cn;p=xxxx
C: text/html-fragment
K: SaveHistory
L: 121
<Font Face='Arial' Color='-16777216' Size='9'>hello! </Font><Font Face='SimSun' Color='-16777216' Size='12'>测试</Font>
这就是用户A向对方发的即时消息,内容是“hello!测试"。这里用的是SIP Message方法,消息体是XML表示的即时消息,消息头跟INVITE相似。
第六步:111.111.111.111:1111 <<<<<<<< 221.130.45.203:8080
SIP-C/2.0 200 OK
Q: 2 M
T: sip:123456798@fetion.com.cn;p=xxxx
I: 16
D: Mon, 01 Mar 2007 00:00:00 GMT
XI: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
这是用户B收到第五步发出的即时消息后回过来的RESPONSE,结果是OK,其中XI这个消息头域的MessageID。
第七步:111.111.111.111:1111 >>>>>>>> 221.130.45.203:8080
B fetion.com.cn SIP-C/2.0
F: 123456789
I: 16
Q: 3 B
T: sip:987654321@fetion.com.cn;p=xxxxx
这是用户A开始关闭聊天窗口准备结束聊天了,向用户B发出了一个BYE的SIP请求消息。
第八步:111.111.111.111:1111 <<<<<<<< 221.130.45.203:8080
SIP-C/2.0 200 OK
Q: 3 B
T: sip:123456789@fetion.com.cn;p=xxxx
I: 16
这是最后用户B对对用户A发出的BYE的回复。
在用户B那边,整个交互过程跟用户A这边对应,用户A在发出INVITE,要求和B会话,而用户B这边则是回应邀请。
那发短信是怎么样的呢?也基本差不多,如发一个内容为test的短信到用户B时的SIP Message请求消息是这样的:
111.111.111.111:1111 >>>>>>>> 221.130.45.203:8080
M fetion.com.cn SIP-C/2.0
F: 12345678
I: 16
Q: 1 M
T: sip:987654321@fetion.com.cn;p=xxxx
N: SendSMS
L: 4
test
以上分析都是飞信通过TCP直连方式工作时的情况,飞信通过HTTP直连呢?工作过程跟上面完全一样,不同的是,连接的是221.130.45.203:80,协议是HTTP,采用的POST请求是:
POST /ht/sd.aspx?t=s&i=2 HTTP/1.1
POST的数据分就是上面一样的SIP消息了。