SIP 協議詳解
阿新 • • 發佈:2020-03-07
## 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