摘要
会话发起协议 (SIP) 是对电信行业具有重大意义的信令协议。本文从技术角度对 SIP 进行了一般介绍,并说明 SIP 如何成为电信解决方案的重要支持因素。
简介
我曾经构想过一种软件,它可以“浮”在应用程序之上,提供辅助作用。不过,这不是一个哑的“帮助”系统,而是一个实时技术支持代理,在 Internet 上进行讨论。那时别人告诉我,“现有的工具、库、协议或带宽实现不了这样的要求!”
时代不同了。
许多人家里已经拥有基于 DSL、电缆和其他技术的宽带网络。高质量的工具和库到处都是,无论是商业的还是开源的。还出现了支持应用的各种标准。现在是实施这一奇思妙想的时候了。
SIP 初探
让我来向您介绍 SIP,即会话发起协议。SIP 是一种轻型的可扩展请求/响应协议,用于在两个端点之间开始通信会话。这听起来是不是很熟悉?SIP 在概念上源自于 HTTP 和 SMTP,尽管其目的不同。SIP 消息相当于 CB 专业术语 10-代码和 Q 信号。
图 1. 用于管理 CB 呼叫的专业术语
在本示例中,实际消息包含在专用的呼叫协商消息中。
SIP 是 IETF 于 1999 年提供的,在 2002 年进行了修订。RFC 3261 中对此进行了说明。本文中许多有关 SIP 的信息均选自该 RFC。SIP 有许多扩展,其中许多可在 SIP 相关 RFC 和草案清单中找到。
SIP 有哪些优点?通常情况下,两个端点使用它来协商一次“呼叫”。“协商”是指介质(文本、语音等)、传输(通常是 RTP,即实时协议)和编码(编解码器)。一旦协商成功,两个端点将使用选定的方法相互交谈 — 这就与 SIP 无关了。“呼叫”完成后,使用 SIP 指示断开连接。因此,SIP 最好用作一种信令机制。SIP 及其扩展还提供一些相关功能,如即时消息传递、注册和在线状态。
SIP 术语中的端点被称为用户代理。它可以是“软件电话”、即时信使、IP 电话,甚至是手机。服务器用户代理(如注册器、代理或应用服务器)提供集中服务。
SIP 听起来很简单,实际上也的确如此。尽管这种简单性对于协议的稳定很重要,但它并未限制协议的有用性,其应用领域非常广泛。
例如,考虑一下 HTTP。协议定义本身很小。但其用途是无限的。SIP 也可以扩展。SIP 已有数十种扩展,覆盖范围广泛的各种应用。现在我们来深入了解 SIP 并探究它为什么如此重要。
SIP 重要吗?
有人说,SIP 之于电信就像 HTTP 之于 Web。
SIP 在电信行业中举足轻重。蜂窝技术公司已决定在 SIP 的基础上进行标准化,以应对所有未来的应用。VoIP(IP 电话)供应商、Internet 电话和即时消息传递应用程序(如 Microsoft MSN Messenger)都准备在 SIP 的基础上进行标准化。
有些信令协议以及对等技术已经存在。这就引发了一个问题:与这些协议和技术相比,SIP 有何优势?SIP 提供了如下显著优势:
- 稳定性:该协议已使用多年,坚如磐石。
- 速度:这个基于 UDP 的小型协议效率极高。
- 灵活性:这个基于文本的协议十分容易扩展。
- 安全性:提供了像加密(SSL、S/MIME)和身份验证这样的特性。SIP 扩展提供了其他安全特性。
- 标准化:随着整个电信行业都在向 SIP 靠拢,SIP 已经迅速成为一种标准。其他技术可能在某些方面优于 SIP,但它们没有得到全球范围内的采用。
这意味着如果您希望您的应用程序与其他工具、设备和服务器进行互操作,SIP 是最佳选择。供应商对互操作性很重视,会定期开会对其产品进行测试。这些会议称为 SIPit for SIP 互操作性测试(以前叫做 Bakeoff,是 Pillsbury 提出改名的)。
剖析 SIP 呼叫
现在我们来仔细研究此技术。SIP 通常基于 UDP 进行传输,但是 SIP 工具必须同时支持 TCP。SIP 消息包含两部分:
- 信封,以头字段的形式描述请求或请求的结果(响应)。
- 可选的负载,即内容,包含有关请求的数据。
信封是文本,但内容可以是文本也可以是二进制数据。
例如,我们来具体分析一个典型的 SIP 呼叫。在本案例中,用户 A 希望呼叫用户 B。图 2 显示了此呼叫:
图 2. 典型的 SIP 呼叫
下面对所有这些消息进行了说明:
1. 用户代理 A 向用户代理 B 发送一个 SIP 请求“INVITE”,表示用户 A 希望与用户 B 交谈。此请求包含语音流协议的详细信息。为此,在负载中使用了会话描述协议 (SDP)。SDP 消息包含用户 A 支持的所有媒体编解码器列表。(这些编解码器使用 RTP 进行传输。) | INVITE sip:UAB@example.com SIP/2.0 Via: SIP/2.0/UDP 10.20.30.40:5060 From: UserA <sip:UAA@example.com>;tag=589304 To: UserB <sip:UAB@example.com> Call-ID: 8204589102@example.com CSeq: 1 INVITE Contact: <sip:UserA@10.20.30.40> Content-Type: application/sdp Content-Length: 141 v=0 o=UserA 2890844526 2890844526 IN IP4 10.20.30.40 s=Session SDP c=IN IP4 10.20.30.40 t=3034423619 0 m=audio 49170 RTP/AVP 0 a=rtpmap:0 PCMU/8000 |
2. 用户代理 B 读取该请求,然后告诉用户代理 A 它已收到请求。 | SIP/2.0 100 Trying From: UserA <sip:UAA@example.com>;tag=589304 To: UserB <sip:UAB@example.com> Call-ID: 8204589102@example.com CSeq: 1 INVITE Content-Length: 0 |
3. 当电话响铃时,用户代理 B 向用户代理 A 发送临时消息(响铃)以避免超时和放弃。 | SIP/2.0 180 Ringing From: UserA <sip:UAA@example.com>;tag=589304 To: UserB <sip:UAB@example.com>;tag=314159 Call-ID: 8204589102@example.com CSeq: 1 INVITE Content Length: 0 |
4. 最终,用户 B 决定接受该呼叫。此时,用户代理 B 向用户代理 A 发送 OK 响应。在响应的负载中,还有另一个 SDP 消息。它包含两个用户代理均支持的一组媒体编解码器。此时两方正式进入通话。使用 200 类型的响应可以接受所有类型的 SIP 请求。 | SIP/2.0 200 OK From: UserA <sip:UAA@example.com>;tag=589304 To: UserB <sip:UAB@example.com>;tag=314159 Call-ID: 8204589102@example.com CSeq: 1 INVITE Contact: <sip:UserB@10.20.30.41> Content-Type: application/sdp Content-Length: 140 v=0 o=UserB 2890844527 2890844527 IN IP4 10.20.30.41 s=Session SDP c=IN IP4 10.20.30.41 t=3034423619 0 m=audio 3456 RTP/AVP 0 a=rtpmap:0 PCMU/8000 |
5. 用户代理 A 最后使用一条 ACK 消息进行确认。对于此类请求,即使消息丢失,也不会有重试和响应消息。ACK 仅用于 INVITE 消息。 | ACK sip:UAB@example.com SIP/2.0 Via: SIP/2.0/UDP 10.20.30.41:5060 Route: <sip:UserB@10.20.30.41> From: UserA <sip:UAA@example.com>;tag=589304 To: UserB <sip:UAB@example.com>;tag=314159 Call-ID: 8204589102@example.com CSeq: 1 ACK Content-Length: 0 |
6. 两个用户代理现在使用上一条 SDP 消息中选择的方法进行连接。 | 通过端口 49170 和 3456 使用 PCMU/8000 编码进行双向传输的 RTP 音频数据包 |
7. 在通信会话结束时,其中一个用户挂断。此时该用户的用户代理发送一条新的请求 BYE。此消息可由任一方发送。 | BYE sip:UAB@example.com SIP/2.0 Via: SIP/2.0/UDP 10.20.30.41:5060 To: UserB <sip:UAB@example.com>;tag=314159 From: UserA <sip:UAA@example.com>;tag=589304 Call-ID: 8204589102@example.com CSeq: 1 BYE Content-Length: 0 |
8. 另一个用户的用户代理接受 BYE 请求,然后使用一条 OK 消息进行回复。呼叫断开。 | SIP/2.0 200 OK To: UserB <sip:UAB@example.com>;tag=314159 From: UserA <sip:UAA@example.com>;tag=589304 Call-ID: 8204589102@example.com CSeq: 1 BYE Content-Length: 0 |
SIP 消息的第一行包含消息的类型和所用 SIP 的版本 (2.0)。在请求中,此行还包含一个被称作 SIP URI 的地址。这代表消息的目的地。
本示例演示了如何使用请求消息 INVITE、ACK 和 BYE,以及 200 OK 响应消息。SIP 中还有许多其他消息。以下是几种请求:
消息 | 用法 |
INVITE | 呼叫用户代理,传输呼叫。 |
ACK | 确认呼叫。 |
BYE | 结束呼叫。 |
CANCEL | 终止尚未确认的呼叫。 |
REGISTER | 提供注册器服务,包含联系人地址以及可以替代使用的别名。例如,在上例中,地址 sip:UAA@example.com 是 sip:UserA@10.20.30.40 的别名。然后,注册器服务器 example.com 可以将致 UAA 的呼叫转发到地址 10.20.30.40。 |
OPTIONS | 询问用户代理的“能力”(如,该用户代理理解的消息和编解码器)。 |
以下是一些常用的响应消息:
消息 | 用法 |
100 Trying | 最终用户代理已收到消息,但尚未对其进行处理。请等待。 |
180 Ringing | 最终用户代理已收到消息,正在提示用户。请等待。 |
200 OK | 最终用户已经接受消息。 |
301 Moved Permanently 和 302 Moved Temporarily | 用户代理地址已更改;Contact 字段中提供了新的永久或临时地址。 |
400 Bad Request | 普通错误消息。客户端不能理解收到的消息。 |
401 Unauthorized 和 407 Proxy Authentication Required | 请使用凭证重试。 |
404 Not Found | 您尝试联系的用户不存在或尚未注册。 |
408 Request Timeout | 另一方未响应。这意味着某条 SIP 消息从未获得确认。所有重试也均被丢弃。这并不意味着电话响铃时间过长(电话可以一直响下去)。 |
消息使用类似的头字段类型。下面给出其中一些:
头字段 | 用法 |
From | SIP 请求的发送方。 |
To | SIP 请求的接收方。通常这与 SIP URI(可以是“别名”或实际地址)相同。 |
Contact | 用户代理的实际地址。 |
Call-ID | 这不是主叫方的电话号码。它唯一表示两个用户代理之间的整个呼叫或对话。所有相关的 SIP 消息使用同一个 Call-ID。例如,当用户代理收到一条 BYE 消息时,它就可以根据 Call-ID 知道要挂断哪个呼叫。 |
CSeq | 消息的序列号。这在一个对话或 Call-ID 中是唯一的,用于区分新消息和“重试消息”。当初始消息未即时收到确认时,就会发生重试,并会定时发送。 |
Content-Type | 消息内部负载的 MIME 类型。 |
Content-Length | 负载的大小(以字节为单位)。信封和负载由一空行分隔。 |
还有一些与消息路由功能相关的头字段,如 Via、Route 和 Record-Route。许多头字段提供了像 Accept、User-Agent 和 Supported 这样的功能。其他头字段则提供像 Authorization、Privacy 和 WWW-Authenticate 这样的安全功能。还有许多其他头字段。而且,其中许多字段都有缩写语法(例如,From = f、To = t 等等)。
SIP 的其他功能
使用 SIP 及其扩展可以实现很多应用:
- VoIP
- 视频会议
- 文本和数据的即时消息传递,如 MSN Instant Messenger
- 注册(我在线!)
- 在线状态(好友在不在?)
- 点击通话(单击这里可与技术支持代理交谈)
- 应答机/交互式语音响应 (IVR) 系统(“请输入您的口令。请记录您的姓名。英文请按 1,西班牙语请按 2...”)
- 网络游戏(如 Quake)和一些手机游戏(甚至基于语音和 IM)
- 手机应用程序
- 移动电子商务
基本上,如果是两个端点之间进行通信,SIP 就能实现。
但对于我的通过 Web 的实时技术支持代理的妙想又如何呢?目前能不能通过 SIP 来实现?能否通过我喜爱的 Java 语言来实现呢?简而言之,可以。
Java 中的 SIP
我经常使用 SIP。我可以肯定地说,Java 提供了非常绝佳的 SIP 支持。许多对 SIP 开发人员有帮助的 Java 技术提取了许多与开发 SIP 应用程序有关的详细信息。这些主要存在于 JAIN(适用于集成网络的 Java API)工作组中:
- JAIN SIP API (JSR 32)
- SIP Servlet API (JSR 116)
- JAIN SIP Lite (JSR 125)
- SIP API for J2ME (JSR 180)
- JAIN SIMPLE Presence (JSR 164)
- JAIN SIMPLE Instant Messaging (JSR 165)
其他相关技术有:
- JAIN SDP (JSR 141)
- Java Media Framework for RTP(J2SE 可选程序包,非 JAIN)
如果您希望开发客户端应用程序,就需要一个客户端 SIP 引擎,即“堆栈”。此处提供了一个优秀的开源 Java SIP 堆栈。它还支持 SDP。如果不想开发自己的 SIP 电话,您可以使用这个。
总结
本文简要介绍了 SIP、其可能的使用场景,以及一点 SIP 语法。还大致给出了与 SIP 相关的各种 Java 技术。尽管本文并未详细讨论,但希望它足以引起您的兴趣,并促使您开始使用 SIP。SIP 的时代已经到来,许多很酷的想法现在终于可以实现。