SIP协议参考文档

164 阅读8分钟

前言

随着产品线的不断发展,公司的产品越来越多,为了提升产品的竞争力,在使用 SIP 协议实现通话,本着普及 SIP 知识点出发,编写此文。

概述

1. SIP 简述

SIP(Session Initiation Protocol),中文翻译为 会话初始协议,它是一种应用层协议,用于在IP网络中建立、修改和终止多媒体会话。这些会话包括但不限于语音通话、视频通话、即时消息传递和在线游戏等。SIP协议由IETF(Internet Engineering Task Force)制定,主要用于实时通信服务。

SIP 采用了基于文本的格式,消息使用类似HTTP的请求-响应模式进行传输。它使用URL(Uniform Resource Locator)来标识会话参与者,可以包含用户的电话号码、IP地址或其他标识符。SIP还支持用户身份验证和安全性,通过使用TLS(Transport Layer Security)和S/MIME(Secure/Multipurpose Internet Mail Extensions)等协议提供通信的保密性和完整性。

2. SIP 请求

SIP 还是一个对等的协议,类似于 P2P ,不像传统电话那样必须有一个中心的交换机,它可以在不需要服务器的情况下进行通信,只要通信双方都彼此知道对方地址(或者,只有发起 SIP 通话方知道 SIP 接收方地址)。

例如:A 的 IP 地址是 172.16.27.10,端口是 6000,B 的 IP 地址是 172.16.27.11,端口是 6000。当 A 呼叫 B 时,他只需要直接呼叫 B 的 SIP 地址:sip:A@172.16.27.11:6000,反过来 B 呼叫 A 时,只需要呼叫 A 的 SIP 地址:sip:B@172.16.27.10:6000。

下面是 A 呼叫 B 的完整流程:

A               B
|               |
|    INVITE | -----------------> 发起 INVITE 请求
|--------------------> |
|    100 Trying | -----------------> 请求正在处理中
|<-------------------- |
|    180 Ringing       | -----------------> 被呼叫方设备开始响铃
|<-------------------- |
|    200 OK           | -----------------> 表示会话已建立
|<-------------------- |
|    ACK               | -----------------> 确认会话建立
|--------------------> |
|                     |
|<---RTP------------> |
|<---RTP------------> | -----------------> 通过 RTP 传输音频数据
|<---RTP------------> |
|    ...               |
|                     |
|    BYE               | -----------------> 双方都可以发送 BYE 以终止会话
|<-------------------> |
|    200 OK           | -----------------> 确认会话终止
|--------------------> |
|                     |

2.1. INVITE 请求结构

上文中,我们举了 A 呼叫 B 的例子,A 与 B 发起通话时,会发起 INVITE 请求,在这个请求里携带了 INVITE 的请求结构,完整的请求结构包含了请求行、消息头、消息体三个部分,以下是 INVITE 请求示例:

INVITE sip:172.16.27.11:6000 SIP/2.0

Via: SIP/2.0/UDP 172.16.27.10:6000;branch=z9hG4bK776asdhds

Max-Forwards: 70

From: sip:172.16.27.10:6000;tag=1928301774

To: sip:172.16.27.11

Call-ID: a84b4c76e66710@pc33.example.com

CSeq: 314159 INVITE

Allow:INVITE, ACK, OPTIONS, CANCEL, BYE, REFER, INFO, NOTIFY, MESSAGE, SUBSCRIBE

Contact: sip:alice@pc33.example.com

Content-Type: application/sdp

Content-Length: 142

v=0

o=alice 2890844526 2890844526 IN IP4 pc33.example.com

s=Session SDP

c=IN IP4 172.16.27.10

t=0 0

m=audio 49170 RTP/AVP 0

a=rtpmap:0 PCMU/8000

2.1.1. 请求头

INVITE sip:172.16.27.11:6000 SIP/2.0

INVITE:请求方法,表示发起一个会话。

sip: 172.16.27.11:6000:请求URI,表示被呼叫方的SIP地址。

SIP/2.0:SIP 协议版本。

2.1.2. 消息头

Via: SIP/2.0/UDP 172.16.27.10:6000;branch=z9hG4bK776asdhds

Via:指明请求经过的路径和发送者的消息。

branch:标识请求(唯一)。

Max-Forwards: 70

Max-Forwards: 限制请求经过的最大跳数,防止循环。

From: sip:172.16.27.10:6000;tag=1928301774

To: sip:172.16.27.11

Form:呼叫方的 SIP 地址。

tag:区分不同的会话。

To:被呼叫方的 SIP 地址。

Call-ID: a84b4c76e66710@pc33.example.com

CSeq: 314159 INVITE

Allow:INVITE, ACK, OPTIONS, CANCEL, BYE, REFER, INFO, NOTIFY, MESSAGE, SUBSCRIBE

Contact: sip:alice@pc33.example.com

Content-Type: application/sdp

Content-Length: 142

Call-ID:会话的唯一标识符。

CSeq:序列号和请求方法,用于排序和匹配请求和响应。

Allow:发送方支持的SIP请求方法。

Contact:提供可以联系到主叫方的地址。

Content-Type:描述消息体的媒体类型。

Content-Length:消息体的长度,以字节为单位。

2.1.3. 消息体

SIP 请求的消息体,是由 SDP(Session Description Protocol,会话描述协议)组成的,通常位于 SIP 请求中空行后面的文本。SDP 是一种格式,用于描述多媒体通信会话的信息,以便参与者可以了解会话的细节。

v=0

o=alice 2890844526 2890844526 IN IP4 172.16.27.10

s=Session SDP

t=0 0

c=IN IP4 172.16.27.10

m=audio 49170 RTP/AVP 0

a=sendrecv

v=:SDP版本。

o=:会话创建者和会话的 ID。

s=:会话名称。

t=:会话的起始和结束时间。

c=:会话的连接信息。

m=:媒体描述。

a=:会话属性,表示接收模式。SIP 的接收属性有四种,分别是 sendrecv、recvonly、sendonly、inactive。具体的用途如下:

  • sendrecv:是默认参数,表明终端既能发送也能接收媒体流。
  • recvonly:表示该终端仅接收媒体,不发送任何媒体流。
  • sendonly:表示该终端仅发送媒体,但不期望接收任何媒体流。
  • inactive:表示该媒体流既不发送也不接收媒体。

3. 基于 SIP 协议的客户端方案

3.1. Linphone

目前最流行的 SIP 开源客户端,现如今做 SIP 的基本上都用他家的客户端做测试,或者直接集成 Linphone SDK 到自己的 App 上。

Linphone 支持 iOS、Android、Mac、Windows、Linux,既有 GUI 端,也有 Console 端,这也是很多人选择它的原因吧。

Linphone 的开源协议是 GNU GPLv3 ,你可以免费用源代码,但是改了它的代码你也要开源,当然它还有付费的服务。

Linphone 的核心是Liblinphone,底层是 C 语言写的,上层应用基于不同平台封装了不同的接口,比如桌面端有 C++封装接口,iOS 端是 Swift 封装接口,Android 是 Java 封装接口等。

Liblinphone 的核心组件有三个:

    • Mediastreamer2:处理音视频,为了解决回音消除的问题,在 2013 年就整合了 WebRTC 的 AEC 算法。
    • oRTP:RTP 库。
    • belle-sip:早期使用的是 oSIP,后来 Linphone 自己重写了协议栈,取名 belle-sip。

官网链接:Linphone

3.2. PJSIP

PJSIP 是一个用 C 语言编写的免费开源多媒体通信库,可实现基于标准的协议,例如 SIP、SDP、RTP、STUN、TURN 和 ICE。它将信令协议 (SIP) 与丰富的多媒体框架和 NAT 遍历功能结合到高级 API 中,该 API 可移植且适用于从台式机、嵌入式系统到移动手机的几乎所有类型的系统。

PJSIP 既紧凑又功能丰富。它支持音频、视频、状态和即时消息,并具有丰富的文档。PJSIP 非常便携。在移动设备上,它抽象了系统相关的功能,并且在许多情况下能够利用设备原生的多媒体功能。

PJSIP 由一个自2005 年以来专门为该项目工作的小团队开发,有来自世界各地的数百名开发人员参与,并且自 2007 年以来在 SIP 互操作性事件(SIPit)上定期测试。

官网链接:PJSIP

4. SIP 与其它会话协议的比对

/SIPH.323WebRTC
协议制定者IETFITU-TW3C、IETF
目的多媒体对话多媒体对话在Web浏览器和移动应用中提供简单、高效的实时通信能力,无需依赖任何插件或客户端安装
信令控制方式请求 - 响应H.225依赖于外部信令系统(如SIP、WebSocket、XMPP等)
复杂度简单复杂复杂
编码方式文本二进制文本
媒体能力描述SDPH.245SDP
多媒体能力支持支持支持
个人移动性支持部分支持支持
支持终端支持硬件 IP 电话、软件客户端支持各种终端设备Chrome、Edge、Firefox、移动浏览器、原生App
协议扩展性优秀一般良好
协议兼容性良好优秀良好

5. SIP 实现单向通话思路

5.1. 限制或阻止 RTP 双向流的输出

在上文中,我们提到了 SIP 的请求。在 SIP 完成连接后,通话双方会使用 RTP(Real-time Transport Protocol)协议来实时传输音频和视频等媒体数据。如果需要实现 A 呼叫 B,B 只能接收到 A 的 RTP 流,而 A 无法接收到 B 的 RTP 流的单向通话,在传输 RTP 流的时候可以通过关闭麦克风等手段限制其中一方的 RTP 流,以实现单向通话。

5.2. 修改 SIP 的 SDP 报文

SIP 的 SDP 报文,描述了 SIP 会话的详细信息,如媒体类型、格式、传输地址等。当使用 SIP 来建立通信会话时,SDP 报文通常作为 SIP 消息的一个组成部分被携带,以帮助通信双方协商媒体参数。在 SDP 报文中,使用了 a= 来表示 SIP 的会话属性,这个 a= 的会话属性默认为 sendrecv,将其改为 sendonly 即可实现单向发送音频。

6. 附录

6.1. 参考文献