扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
摘要
会话发起协议(Session Initiation Protocol,SIP)是一种信令协议,它对于通信业有着重要的意义。本文从技术上对SIP进行了一般性的介绍,并说明了SIP如何为通信解决方案提供重要支持。
简介
我曾经构想过一种软件,它可以“浮于”应用程序之上,提供辅助作用。这不是一个哑的“帮助”系统,而是一个活动的技术支持代理,可以在Internet上进行讨论。那时曾有人告诉我,“现有的工具、库、协议或带宽实现不了这样的要求!”
时代已经不同了!
许多人家中已经拥有基于DSL、光纤和其他技术的宽带网络。存在大量高质量的工具和库,无论是商业的还是开源的。标准驱动应用。现在是时候来实现上述创新思路了。
了解SIP
首先,我将向您介绍SIP,也就是会话发起协议。SIP是一种轻量级的可扩展请求/响应协议,用于在两个端点之间开始通信会话。这听起来是不是很熟悉?SIP在概念上源自于HTTP和SMTP,但是它的目的却不同。可以把SIP消息与CB(民用波段)隐语10-code和Q-signal进行比较。
图1.用于管理CB呼叫的隐语 |
在这个例子中,真正的消息包含在专用的呼叫协商消息中。
SIP是IETF于1999年提出的,在2002年进行了修订。RFC 3261对它进行了描述。本文中有关SIP的信息就选自RFC。对SIP存在很多扩展,这些扩展中的很多都能在SIP-related RFCs and drafts清单中找到。
SIP有哪些优点呢?通常情况下,两个端点使用它来协商一次“呼叫”。这里的协商包括介质(文本、语音等)、传输(通常是RTP、Real Time Protocol)和编码(codec)。一旦协商成功,两个端点就会使用选中的方法相互交谈——这就与SIP无关了。“呼叫”完成之后,SIP用于指示断开连接。因此,SIP最好用作一种信令机制。SIP及其扩展还提供一些相关功能,比如即时消息传递、注册和到场。
SIP术语中的端点叫做用户代理。它可以是“软件电话”、即时消息收发器、IP电话,甚至是手机。服务器用户代理提供集中式的服务,比如登记员、代理或应用服务器。
听起来SIP非常简单,而且它也确实简单。这种简单性对于协议的稳定很重要,而且它也没有降低协议的有用性,所以该协议得到了广泛的应用。
例如,考虑一下HTTP。协议本身的定义很少。但是使用它的方式多不胜数。SIP也是可以扩展的。存在大量针对SIP的扩展,它们涵盖了很多应用。现在,我们进一步来考察SIP,并分析它为什么会如此重要。
SIP的重要性
有人说,SIP对于通信,就像HTTP对于Web一样。
SIP对通信业产生了巨大的影响。从事蜂窝技术的公司已经决定为了未来的应用,对SIP进行标准化。VoIP (Voice over IP)供应商、Internet电话和即时消息传递应用程序(例如,Microsoft MSN Messenger)都准备基于SIP进行标准化。
目前已经存在一些信令协议和P2P技术。这就引发了一个问题:SIP相对于这些协议和技术有何优势?SIP具有以下的明显优点:
稳定性。该协议已经使用了多年,现在十分稳定。
速度。基于UDP的小型协议效率特别高。
灵活性。这个基于文本的协议十分容易扩展。
安全性。它提供像加密(SSL、S/MIME)和身份验证这样的功能。对SIP的扩展还提供其他安全性功能。
标准化。随着整个通信行业都在向SIP靠拢,SIP已经讯速成为一种标准。其他技术可能具有SIP所没有的优势,但是它们没有得到全球范围内的采用。
这意味着,如果您想让您的应用程序与其他工具、设备和服务器进行互操作,SIP是最佳选择。供应商对互操作性是很关注的,会定期开会对其产品进行测试。这些会议称为SIPit for SIP Interoperability Tests(以前叫做Bakeoff,是Pillsbury提出更改的)。
剖析SIP呼叫
现在,让我们更深入地了解这门技术。SIP通常基于UDP进行传输,但是SIP工具必须同时支持TCP。一条SIP消息由两部分组成:
信封(envelope),以头字段的形式描述一个请求或请求的结果(响应)。
有效负载(payload),即内容(可选),包含有关请求的数据。
信封是文本格式,但是内容可以是文本,也可以是二进制格式。
例如,让我们具体分析一次典型的SIP呼叫。在这个场景中,用户A想呼叫用户B。图2说明了这次呼叫:
图2. 一次典型的SIP呼叫 |
下面对所有的消息进行了解释:
1. User Agent A发送一个SIP请求INVITE给User Agent B,表达User A想跟User B进行谈话的愿望。这个请求包含语音流协议的细节。 payload中使用会话描述协议(Session Description Protocol,SDP) 就是为此目的。SDP消息包含一个清单,其内容为User A支持的所有介质编码。(这些编码使用RTP进行传输。) |
INVITE sip:UAB@example.com SIP/2.0 Via: SIP/2.0/UDP 10.20.30.40:5060 From: UserA To: UserB Call-ID: 8204589102@example.com CSeq: 1 INVITE Contact: 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. User Agent B读取该请求,然后告诉User Agent A它已经收到请求。 | SIP/2.0 100 Trying From: UserA To: UserB Call-ID: 8204589102@example.com CSeq: 1 INVITE Content-Length: 0 |
3.当电话响铃时,User Agent B发送临时消息(响铃)给User Agent A,这样它就不会超时和放弃。 |
SIP/2.0 180 Ringing From: UserA To: UserB Call-ID: 8204589102@example.com CSeq: 1 INVITE Content Length: 0 |
4.最终,User B决定接受呼叫。此时,User Agent B发送一个OK响应给User Agent A。在响应的payload中,还有另一条SDP消息。它包含一组两个用户代理都支持的介质编码。此时,双方正式处于呼叫中。使用200类型的响应可以接受所有类型的SIP请求。 |
SIP/2.0 200 OK From: UserA To: UserB Call-ID: 8204589102@example.com CSeq: 1 INVITE Contact: 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. User Agent A最后使用一条ACK消息进行确认。对于这种请求类型来说,没有重试和响应消息,即使消息丢失。ACK只在INVITE消息中使用。 |
ACK sip:UAB@example.com SIP/2.0 Via: SIP/2.0/UDP 10.20.30.41:5060 Route: From: UserA To: UserB Call-ID: 8204589102@example.com CSeq: 1 ACK Content-Length: 0 |
6..两个用户代理现在使用最后一条SDP消息中选定的方法进行连接。 |
RTP使用PCMU/8000编码对在端口49170 & 3456上双向传输的音频数据进行打包。 |
7.在通信会话结束时,其中一个用户挂断。此时,这个用户的用户代理发送一个新的请求BYE。这条消息可以由任一方发送。 |
BYE sip:UAB@example.com SIP/2.0 Via: SIP/2.0/UDP 10.20.30.41:5060 To: UserB From: UserA Call-ID: 8204589102@example.com CSeq: 1 BYE Content-Length: 0 |
8.另一用户的用户代理接受该请求,然后使用一条OK消息作为应答。呼叫连接至此断开。 |
SIP/2.0 200 OK To: UserB From: UserA 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 | 终止还未OK的呼叫。 |
REGISTER | 提供一项注册服务,带有一个联系地址和可以用来代替的别名。例如,在前面的例子中,地址sip:UAA@example.com就是sip:UserA@10.20.30.40的别名。然后,注册服务器example.com就可以把呼叫转发给地址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消息永远不会OK。所有重试都将被丢弃。这并不意味着电话响太长时间(电话可以永远响铃)。 |
消息使用类似的头字段类型。下面给出其中的一些:
头字段 |
用法 |
---|---|
From | SIP请求的发送者。 |
To | SIP请求的接受者。这通常与SIP URI相同(可以是一个“别名”或一个实际地址)。 |
Contact | 用户代理的实际地址。 |
Call-ID | 这并不是呼叫者的电话号码。它惟一地代表两个用户代理之间的完整呼叫或对话。所有相关的SIP消息都使用同一个Call-ID。例如,当一个用户代理收到一条BYE消息,根据Call-ID,它就知道要挂断哪次呼叫。 |
CSeq | 消息的顺序编号。这在一次对话或一个Call-ID中是惟一的。这用于区别新的消息和“重试消息”。当一条初始消息没有及时OK时,重试就会进行,并会定时发送。 |
Content-Type | 消息内payload的MIME类型。 |
Content-Length |
payload的大小,以字节为单位。信封和payload之间由一空行隔开。 |
还有一些与消息路由选择功能相关的头字段,如:Via、Route和Record-Route。许多头字段提供像Accept、User-Agent和Supported这样的功能。其他头字段则提供像Authorization、Privacy和WWW-Authenticate这样的安全性功能。还有很多其他的头字段存在。此外,这些字段中许多都有缩写语法(比如,From = f,To = t,等等)。
SIP的其他功能
使用SIP及其扩展可以实现很多应用:
VoIP
视频会议
针对文本和数据的即时消息传递,比如MSN Instant Messenger
注册(我在线!)
到场(我的伙伴在不在?)
Click-to-talk(点击通话,即点击这里便可与一个技术支持代理交谈)
应答机器/互动式语音应答(Interactive Voice Response,IVR)系统(“请输入您的密码。请记录您的姓名。英文请按1,西班牙语请按2…”)
网络游戏,比如Quake和一些手机游戏(甚至基于语音和IM)
基于手机的应用程序
移动电子商务
基本上,如果是两个端点之间进行通信,SIP就能完成。
但是,关于活动的Web技术支持代理的想法又如何呢?现在我们能否使用SIP来实现它?我们能否使用Java来实现它?干脆点说,可以。
Java中的SIP
我经常使用SIP。我可以负责任地说,Java为SIP提供了绝佳的支持。Java技术的一个分支把与开发SIP应用程序相关的许多细节抽象出来,这对于SIP开发人员大有帮助。下面这些技术大部分位于JAIN (Java APIs for Integrated Networks)工作组中。
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的时代已经到来,现在使用它可以实现很多很酷的想法。
在本系列文章的第2部分中,我将说明如何使用SIP Servlet API编写一个聊天室应用程序。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。