­

SIP 協議詳解

SIP 協議詳解

2013年參與過一個「影片通訊的App」項目,使用Sip協議通訊。當時通訊協議這塊不是自己負責,加上時間緊、任務重等方面的原因,一直未對Sip協議進行過深入的了解。
2020年春天疫情突發,宅在家裡終於有了空餘時間。這裡來詳細了解一下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。其會話建立過程如下圖所示:

SIP協議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(見RFC3860)格式,可能用message/cpim會好一點,因為已有的IM系統標準是message/cpim格式。

2.2.3 Pager Model請求流程如下

以User1向User2發送MESSAGE消息為例:

Pager Model

  • 步驟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」 https://tools.ietf.org/html/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為例:

Pager Model

步驟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

五、參考:

CPIM消息格式
https://www.xuebuyuan.com/1929719.html

========== THE END ==========

wx_gzh.jpg