這里來詳細了解一下Sip協議。以下內容大致分為以下幾個部分:
- 協議簡介
- 兩種Sip會話模式Session Model與Pager Model;
- Sip 消息體結構
- Sip 消息舉例
一、Sip協議簡介:
SIP(Session Initiation Protocol,會話初始協議)是由IETF(Internet Engineering Task Force,因特網工程任務組)制定的多媒體通信協議。廣泛應用于CS(Circuit Switched,電路交換)、NGN(Next Generation Network,下一代網絡)以及IMS(IP Multimedia Subsystem,IP多媒體子系統)的網絡中,可以支持并應用于語音、視頻、數據等多媒體業務,同時也可以應用于Presence(呈現)、Instant Message(即時消息)等特色業務。可以說,有IP網絡的地方就有SIP協議的存在。
SIP是類似于HTTP,SIP可以減少應用特別是高級應用的開發時間。由于基于IP協議的SIP利用了IP網絡,固定網運營商也會逐漸認識到SIP技術對于他們的原意義。
二、Sip消息的兩種會話模式
在Sip IM通信應用過程中,一般存在著兩種會話模式:
- Session Model
- Pager Model
2.1、Session Model
會話中,對于消息體內容大于1300字節時,一般采用Session Model。其會話建立過程如下圖所示:
主叫方A呼叫被叫方B:
- 步驟1:主叫方A發送INVITE請求到代理服務器;
- 步驟2:代理服務器發送100 Trying 響應主叫方A;
- 步驟3~6:代理服務器搜索被叫方B的地址,獲取地址后轉發INVITE請求;
- 步驟7~9:被叫方B生成的180 振鈴響應,返回給主叫方A;
- 步驟10~12:被叫方B生成的200 OK響應,返回給主叫方A;
- 步驟13~17:主叫方A收到被叫方B200 OK響應后,向被叫方B發送一個ACK,會話建立;
- 步驟18~20:會話結束后,任何參與者(A或B)都可以發送一個BYE請求來終止會話;
- 步驟21~23:主叫方A發送200 OK響應來確認BYE,會話終止。
注:以上的整個流程稱之為一個Dialog
2.2、Pager Model
在Sip消息中,對于消息體不大于1300字節時,一般采用Pager Model。Sip消息通信中采用MESSAGE方法,MESSAGE方法本身并不建立Dialog,在多數應用中,每條IM消息都是獨立的,頗似分頁消息。
2.2.1 MESSAGE方法的由來
RFC3428對Sip協議進行了擴展,在Sip協議中增加了MESSAGE請求方法。采用Pager Model進行通信,傳遞不超過1300字節的數據。MESSAGE方法詳細可參考 “SIP-RFC3428”
https://tools.ietf.org/html/rfc3428。
2.2.2 MESSAGE方法消息體
當User1想給User2發送IM消息時,只需構造一個MESSAGE,發出去即可。
對于其消息體body可以是任何MIME格式。但必須支持plain/text格式,可以選擇支持message/cpim、message/sdp格式,可能用message/cpim會好一點,因為已有的IM系統標準是message/cpim格式。
注:想了解CPIM消息格式的同學可參考:CPIM 消息格式:
https://xiaxl.blog.csdn.net/article/details/104718006
注:想了解SDP消息格式的同學可參考:SDP 消息格式:
https://xiaxl.blog.csdn.net/article/details/104723834
2.2.3 Pager Model請求流程如下
以User1向User2發送MESSAGE消息為例:
- 步驟1:User1發送MESSAGE請求到代理服務器;
- 步驟2:代理服務器轉發User1的MESSAGE請求給USER2;
- 步驟3:User2收到User1的消息后,回復200 OK給代理服務器;
- 步驟7~9:代理服務器轉發200 OK回復給User1
三、SIP消息體格式
SIP消息體結構與Http協議結構相似,均由三部分組成:
- 請求行(request-line) or 狀態行(status-line)
- 消息頭(header)
- 正文(body)
3.1、請求行
請求行格式:Method Request-URI SIP-Version CRLF
請求行舉例:INVITE sip:bob@zte.com SIP/2.0 /r/n
Method
以下列出了幾種消息Method方法:
Method |
方法說明 |
REGISTER |
注冊聯系信息 |
INVITE |
發起會話請求 |
ACK |
INVITE 請求的響應的確認 |
CANCEL |
取消請求 |
BYE |
終結會話 |
OPTIONS |
查詢服務器能力 |
MESSAGE |
RFC3428對Sip協議的擴展,增加了MESSAGE方法。采用Pager Model進行通信,傳遞不超過1300字節的數據。MESSAGE方法詳細可參考 “SIP-RFC3428” |
Request-URI
指示請求的用戶或者服務的地址信息
SIP-Version
請求和響應消息都需要包含SIP版本信息
3.2、狀態行
狀態行格式: SIP-Version Status-Code Reason-Phrase CRLF
狀態行舉例:SIP/2.0 200 OK /r/n
Status-Code狀態碼:
狀態代碼由3位數字組成,表示請求是否被理解或被滿足。
狀態代碼的第一個數字定義了響應的類別,后面兩位沒有具體的分類。
第一個數字有五種可能的取值:
狀態碼 |
含義 |
1xx: |
臨時響應、表示請求消息正在被處理 |
2xx |
成功響應、表示請求已被成功接收完全理解并接收 |
3xx |
重定向響應、表示需采取進一步完成請求 |
4xx |
客戶機錯誤、表示請求消息中包含語法錯誤信息或服務器無法完成客戶機的請求 |
5xx |
服務器錯誤、表示服務器無法合法完成請求 |
6xx |
全局故障 、表示任何服務器都無法完成該請求 |
常用的狀態碼舉例:
狀態碼 |
msg |
含義 |
100 |
Trying |
試呼叫 |
180 |
Ringing |
振鈴 |
181 |
Call is Being Forwarded |
呼叫正在前轉 |
200 |
OK |
成功響應 |
302 |
Moved Temporarily |
臨時遷移 |
400 |
Bad Request |
錯誤請求 |
401 |
Unauthorized |
未授權 |
403 |
Forbidden |
禁止 |
404 |
Not Found |
用戶不存在 |
408 |
Request Timeout |
請求超時 |
480 |
Temporarily Unavailable |
暫時無人接聽 |
486 |
Busy Here |
線路忙 |
504 |
Server Time-out |
服務器超時 |
600 |
Busy Everywhere |
全忙 |
3.3、消息頭
發送MESSAGE消息給user2
MESSAGE sip:user2@domain.com SIP/2.0
Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse
Max-Forwards: 70
From: sip:user1@domain.com;tag=49583
To: sip:user2@domain.com
Call-ID: asd88asd77a@1.2.3.4
CSeq: 1 MESSAGE
Content-Type: text/plain
Content-Length: 18
user2, come here.
Header 字段含義說明:
Header |
含義說明 |
舉例 |
Call-ID |
由本地設備(Client)生成,全局唯一,每次呼叫這個值唯一不變 |
Call-ID: asd88asd77a@1.2.3.4 |
From |
表示請求的發起者 |
From: sip:user1@domain.com;tag=49583 |
To |
表示請求的接受者 |
To: sip:user2@domain.com |
Via |
Via頭域是被服務器插入request中,用來檢查路由環的,并且可以使response根據via找到返回的路 |
Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse |
Max-Forwards |
用于表示這個包最多可以傳送多少跳,每經過一跳都會減一檔Max-Forwards==0系統會返回483。默認為70 |
Max-Forwards: 70 |
Contact |
包含源的URI信息,用來給響應方直接和源建立連接用 |
Contact: sip:192.168.100.1:1111 |
Content-Type |
指明消息體的類型 (SDP會話描述協議) |
Content-Type: text/plain;Content-Type: Application/sdp; Content-Type: application/cpim; |
Content-Length |
指明消息體的字節大小 |
Content-Length: 18 |
四、SIP消息舉例
這里舉兩個例子:
- MESSAGE消息(Pager Mode)
- REGISTER消息
4.1、MESSAGE消息(Pager Model)
以User1發送MESSAGE消息給user2為例:
步驟1:User1發送MESSAGE請求到代理服務器
MESSAGE sip:user2@domain.com SIP/2.0
Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse
Max-Forwards: 70
From: sip:user1@domain.com;tag=49583
To: sip:user2@domain.com
Call-ID: asd88asd77a@1.2.3.4
CSeq: 1 MESSAGE
Content-Type: text/plain
Content-Length: 18
user2, come here.
步驟2:代理服務器轉發User1的MESSAGE請求給USER2
代理服務器收到步驟1請求,到數據庫中查找User2(注冊過程中生成數據庫),隨后生成步驟2的數據。
MESSAGE sip:user2@domain.com SIP/2.0
Via: SIP/2.0/TCP proxy.domain.com;branch=z9hG4bK123dsghds
Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse;
received=1.2.3.4
Max-Forwards: 69
From: sip:user1@domain.com;tag=49394
To: sip:user2@domain.com
Call-ID: asd88asd77a@1.2.3.4
CSeq: 1 MESSAGE
Content-Type: text/plain
Content-Length: 18
user2, come here.
步驟3:User2收到User1的消息后,回復200 OK給代理服務器
直接回應(200-OK) 沒有Body,也不攜帶Contact頭域
SIP/2.0 200 OK
Via: SIP/2.0/TCP proxy.domain.com;branch=z9hG4bK123dsghds;
received=192.0.2.1
Via: SIP/2.0/TCP user1pc.domain.com;;branch=z9hG4bK776sgdkse;
received=1.2.3.4
From: sip:user1@domain.com;tag=49394
To: sip:user2@domain.com;tag=ab8asdasd9
Call-ID: asd88asd77a@1.2.3.4
CSeq: 1 MESSAGE
Content-Length: 0
步驟4:代理服務器轉發200 OK回復給User1
代理服務器收到回復后,去掉最頂端的Via,轉發如下消息給User1
SIP/2.0 200 OK
Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse;
received=1.2.3.4
From: sip:user1@domain.com;;tag=49394
To: sip:user2@domain.com;tag=ab8asdasd9
Call-ID: asd88asd77a@1.2.3.4
CSeq: 1 MESSAGE
Content-Length: 0
4.2、REGISTER消息
首先舉例一個非鑒權注冊消息。
4.2.1 非鑒權注冊消息
192.168.2.161機器發送注冊消息給192.168.2.89服務器:
REGISTER sip:192.168.2.89 SIP/2.0
Via: SIP/2.0/UDP 192.168.2.161:10586
Max-Forwards: 70
From: <sip:01062237496@192.168.2.89>;tag=ca04c1391af3429491f2c4dfbe5e1b2e;epid=4f2e395931
To: <sip:01062237496@192.168.2.89>
Call-ID: da56b0fab5c54398b16c0d9f9c0ffcf2@192.168.2.161
CSeq: 1 REGISTER
Contact: <sip:192.168.2.161:10586>;methods="INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER"
User-Agent: RTC/1.2.4949 (BOL SIP Phone 1005)
Event: registration
Allow-Events: presence
Content-Length: 0
當注冊成功(回送200 OK)時,服務器發送的res消息參考如下:
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.2.161:10586
From: <sip:01062237496@192.168.2.89>;tag=ca04c1391af3429491f2c4dfbe5e1b2e;epid=4f2e395931
To: <sip:01062237496@192.168.2.89>;tag=-00834-14d0805b62bc026d
Call-ID: da56b0fab5c54398b16c0d9f9c0ffcf2@192.168.2.161
CSeq: 1 REGISTER
Allow: INVITE,ACK,OPTIONS,BYE,CANCEL,REGISTER,INFO,UPDATE,PRACK,REFER,SUBSCRIBE,NOTIFY,MESSAGE
Contact: sip:192.168.2.161:10586
Content-Length: 0
Expires: 3600
4.2.2 鑒權注冊消息
當需要鑒權注冊時
- 請求端192.168.2.161發送注冊消息給192.168.2.89服務器
- 服務器對192.168.2.161發送“401 Unauthorized”信息給請求端,提示請求端需要帶上鑒權信息重新注冊
- 請求端帶上鑒權信息后(帶有“Authorization”頭字段)重新向服務器注冊
- 服務器驗證鑒權頭的正確性,如果鑒權成功,給請求端發送200 OK消息。若失敗,繼續發送401消息。
請求端192.168.2.161發送注冊消息給192.168.2.89服務器
REGISTER sip:192.168.2.89 SIP/2.0
Via: SIP/2.0/UDP 192.168.2.161:8021
Max-Forwards: 70
From: <sip:01062237493@192.168.2.89>;tag=efca469543ce4788a6a6a2c7b66cd01f;epid=de4504430d
To: <sip:01062237493@192.168.2.89>
Call-ID: c88a247a74b54a8c9e676bdde3bba6c9@192.168.2.161
CSeq: 1 REGISTER
Contact: <sip:192.168.2.161:8021>;methods="INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER"
User-Agent: RTC/1.2.4949 (BOL SIP Phone 1005)
Event: registration
Allow-Events: presence
Content-Length: 0
服務器對192.168.2.161發送401 Unauthorized信息給請求端,提示請求端需要帶上鑒權信息重新注冊:
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.2.161:8021
From: <sip:01062237493@192.168.2.89>;tag=efca469543ce4788a6a6a2c7b66cd01f;epid=de4504430d
To: <sip:01062237493@192.168.2.89>;tag=-001893-38ba013ba3dde36e
Call-ID: c88a247a74b54a8c9e676bdde3bba6c9@192.168.2.161
CSeq: 1 REGISTER
Allow: INVITE,ACK,OPTIONS,BYE,CANCEL,REGISTER,INFO,UPDATE,PRACK,REFER,SUBSCRIBE,NOTIFY,MESSAGE
Contact: <sip:192.168.2.89:14010>
Content-Length: 0
WWW-Authenticate: Digest realm="192.168.2.89", qop="auth", nonce="e17d377c3d2d9c343e26576a7fd04738481dfc10", opaque="", stale=FALSE, algorithm=MD5
請求端192.168.2.161通過Authorization頭字段帶上鑒權頭信息,發送一個新的REGISTER消息:
REGISTER sip:192.168.2.89 SIP/2.0
Via: SIP/2.0/UDP 192.168.2.161:8021
Max-Forwards: 70
From: <sip:01062237493@192.168.2.89>;tag=efca469543ce4788a6a6a2c7b66cd01f;epid=de4504430d
To: <sip:01062237493@192.168.2.89>
Call-ID: c88a247a74b54a8c9e676bdde3bba6c9@192.168.2.161
CSeq: 2 REGISTER
Contact: <sip:192.168.2.161:8021>;methods="INVITE, MESSAGE, INFO, SUBSCRIBE, OPTIONS, BYE, CANCEL, NOTIFY, ACK, REFER"
User-Agent: RTC/1.2.4949 (BOL SIP Phone 1005)
Authorization: Digest username="01062237493", realm="192.168.2.89", qop=auth, algorithm=MD5, uri="sip:192.168.2.89", nonce="e17d377c3d2d9c343e26576a7fd04738481dfc10", nc=00000001, cnonce="12660455546344082314666316435946", response="f57e47ce03162293b9ced07362ce2b79"
Event: registration
Allow-Events: presence
Content-Length: 0
服務器驗證鑒權頭的正確性,如果鑒權成功,給請求端發送200 OK消息。若失敗,繼續發送401消息
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.2.161:8021
From: <sip:01062237493@192.168.2.89>;tag=efca469543ce4788a6a6a2c7b66cd01f;epid=de4504430d
To: <sip:01062237493@192.168.2.89>;tag=-001894-a5eb977c8969aa51
Call-ID: c88a247a74b54a8c9e676bdde3bba6c9@192.168.2.161
CSeq: 2 REGISTER
Allow: INVITE,ACK,OPTIONS,BYE,CANCEL,REGISTER,INFO,UPDATE,PRACK,REFER,SUBSCRIBE,NOTIFY,MESSAGE
Contact: sip:192.168.2.161:8021
Content-Length: 0
Expires: 3600(xiaxveliang)