1. 程式人生 > >SIP 協議詳解

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](https://upload-images.jianshu.io/upload_images/5969042-5e777956fffba6ec.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 主叫方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`收到`被叫方B`200 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](https://upload-images.jianshu.io/upload_images/5969042-10ec572517864a37.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) + 步驟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:[email protected] 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` ```http MESSAGE sip:[email protected] SIP/2.0 Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse Max-Forwards: 70 From: sip:[email protected];tag=49583 To: sip:[email protected] Call-ID: [email protected] CSeq: 1 MESSAGE Content-Type: text/plain Content-Length: 18 user2, come here. ``` Header 欄位含義說明: | Header | 含義說明 | 舉例 | | --- | --- | --- | | Call-ID | 由本地裝置(Client)生成,全域性唯一,每次呼叫這個值唯一不變 | Call-ID: [email protected] | | From | 表示請求的發起者 | From: sip:[email protected];tag=49583 | | To | 表示請求的接收者 | To: sip:[email protected] | | 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資訊,用來給響應方直接和源建立連線用 | C