当前位置:文档之家› SIP简介

SIP简介

SIP简介
SIP简介

SIP简介,第1部分:SIP初探

时间:2006-04-07

作者:Emmanuel Proulx

浏览次数:

18851

本文关键字:SIP, JAIN, RFC

3261signaling, WebLogic Communications Platform, 会话发起协议, 信令文章工具

推荐给朋友

打印文章

摘要

会话发起协议(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@https://www.doczj.com/doc/3f12146086.html,

SIP/2.0

Via: SIP/2.0/UDP 10.20.30.40:5060 From: UserA

;tag=589304 To: UserB Call-ID: 8204589102@https://www.doczj.com/doc/3f12146086.html, 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

;tag=589304 To: UserB Call-ID: 8204589102@https://www.doczj.com/doc/3f12146086.html, CSeq: 1 INVITE

Content-Length: 0

3.当电话响铃时,User Agent B发送临时消息(响铃)给User Agent A,这样它就不会超时和放弃。SIP/2.0

180 Ringing

From: UserA

;tag=589304 To: UserB

;tag=314159 Call-ID: 8204589102@https://www.doczj.com/doc/3f12146086.html, 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

;tag=589304 To: UserB

;tag=314159 Call-ID: 8204589102@https://www.doczj.com/doc/3f12146086.html, 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@https://www.doczj.com/doc/3f12146086.html, SIP/2.0

Via: SIP/2.0/UDP 10.20.30.41:5060 Route: From: UserA

;tag=589304 To: UserB

;tag=314159 Call-ID: 8204589102@https://www.doczj.com/doc/3f12146086.html, CSeq: 1 ACK

Content-Length: 0

6..两个用户代理现在使用最后一条SDP消息中选定的方法进行连接。RTP使用PCMU/8000编码对在端口49170 & 3456上双向传输的音频数据进行打包。

7.在通信会话结束时,其中一个用户挂断。此时,这个用户的用户代理发送一个新的请求BYE。这条消息可以由任一方发送。BYE

sip:UAB@https://www.doczj.com/doc/3f12146086.html, SIP/2.0

Via: SIP/2.0/UDP 10.20.30.41:5060 To: UserB

;tag=314159 From: UserA

;tag=589304 Call-ID: 8204589102@https://www.doczj.com/doc/3f12146086.html, CSeq: 1 BYE

Content-Length: 0

8.另一用户的用户代理接受该请求,然后使用一条OK消息作为应答。呼叫连接至此断开。SIP/2.0

200 OK

To: UserB

;tag=314159 From: UserA

;tag=589304 Call-ID: 8204589102@https://www.doczj.com/doc/3f12146086.html, CSeq: 1 BYE

Content-Length: 0

SIP消息的第一行包含消息的类型和所使用的SIP版本(2.0)。在请求中,这一行还包含一个叫做SIP URI的地址。这代表消息的目的地。这个例子说明了如何使用请求消息INVITE、ACK和BYE,以及200 OK 响应消息。SIP中还存在许多其他消息。下面给出一些请求:

现在给出一些经常使用的响应消息:

消息使用类似的头字段类型。下面给出其中的一些:

还有一些与消息路由选择功能相关的头字段,如: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编写一个聊天室应用程序。

SIP简介,第2部分:SIP SERVLET

时间:2006-04-19

作者:Emmanuel Proulx

浏览次数:

10614

本文关键字:SIP, Session Initiation

Protocol, JAIN, RFC3261, WebLogic Communications Platform, 会话发起协议, 信令文章工具

推荐给朋友

打印文章

摘要

会话发起协议(Session Initiation Protocol,SIP)是一个重要的信令协议,它正在迅速被电信业采用以构建下一代应用程序。Java是用于SIP开发的极好平台,尤其是在进行服务器端开发时。类似于HTTP servlet,SIP Servlet API使SIP服务的开发变得更轻松。本文将介绍SIP servlet技术,并提供一个带注释的例子。

简介

即时消息传递正在改变人们的生活。它是一个非常有用的工具,结合了电子邮件、Internet电话以及文件传输应用程序的优点。用户甚至可以看到谁在线、谁的状态为“忙碌”。当然了,人们可以用它来长时间地进行不创造任何效益的聊天。但是,员工也可以利用它在老板会见客户时向他发送极为重要的信息。

所以,市场上出现如此多的不同种类的即时消息传递应用程序也就不足为怪了。有这么多的选择应该是一件好事,可是如果员工使用的应用程序与老板使用的不同,那又会怎么样呢?这将是一个大问题,因为这些应用程序大多都使用专有的协议。

SIP为我们带来了福音。SIP很有可能会成为标准的即时消息传递协议。

在本文中,我将开发一个简单的SIP应用程序——一个允许SIP即时messenger (消息传递应用程序)彼此联系并互相传播消息的聊天室服务器端。

SIP SIMPLE

SIMPLE ,即SIP Instant Messaging and Presence Leveraging Extension(SIP即时消息和现场支持扩展)的缩写,是一个工作组以及一组SIP扩展。其中的一个扩展是MESSAGE消息。可以用它来发送包含文本和二进制内容的任意组合的即时消息。这种消息使用起来非常简单,这也是我决定使用它来开发第一个SIP应用程序的原因。

TextClient

为了测试我们的应用程序,我提供了一个小型SIP即时messenger 应用程序(参见文章结尾处的“下载”部分)。该应用程序向其他messenger 或服务器发送MESSAGE消息。用户界面中包含了客户端的地址、好友地址的输入字段、一个文本消息以及一个提交按钮。图1显示了正在运行的TextClient。

图1. 运行中的TextClient

要启动TextClient,只需使用以下命令:

java -jar textclient.jar dev2dev.textclient.TextClient username port

该命令使用JAIN SIP API参考实现作为一个SIP协议栈。我们提供了该工具的源代码,如果您希望了解更多,我推荐您读一下源代码。

ChatRoomServer

下面是示例应用程序的需求

聊天室是一个虚拟空间,不同的即时messenger应用程序可以在其中进行交互。传入聊天室的消息将向聊天室中其他所有的人进行广播。换句话说,所有的消息都可以被所有用户看到。这意味着,当一个消息到达服务器端应用程序时,用户的地址将被添加到一个列表中。然后消息将被发送到该列表中的所有用户。

此外,还可以实现“命令”。命令以正斜杠(/)开头,它不被广播,而是由服务器自己处理,用于特定功能。我将实现的命令包括:

?/join:默默地进入一个聊天室,不广播任何消息。

?/who:打印一份该聊天室所有用户的列表。

?/quit:离开聊天室,不再有消息传入。

SIP Servlet API

SIP Servlet API (JSR 116)是一个服务器端接口,它描述了一个SIP 组件或服务的容器。这正适合用于开发ChatRoomServer。下载该规范,并解压缩。生成的文件夹包括一些库(servlet.jar、sipservlet.jar)以及文档。我无法获得运行示例SIP servlet的参考实现,所以我想您也不必费心去找它了。

SIP servlet最核心的概念是包含。SIP服务是部署或运行在在一个容器或SIP应用服务器上的打包SIP servlet。容器提供了可供应用程序使用的许多服务,比如自动重试、消息调度和排队、分流和归并,以及状态管理。应用程序中只需包含高级的消息处理和业务逻辑。这使SIP服务的开发成为一件轻而易举的事情。

本文的目的不是要提供对SIP Servlet API技术的全面介绍。因此我只简要概述了该API和示例代码,更多信息请参见文章结尾处的“参考资料”部分。

服务器端代码

如果您曾经开发过HTTP servlet,那么服务器端的代码会让您感到非常熟悉。如果您还不知道什么是servlet,您应该首先了解一下。SIP Servlet 规范是HTTP Servlet规范的扩展。其语法、容器行为,甚至方法名都是相似的。

下面我将详细分析该例子。它主要由3个部分组成:

1. 生命周期方法

这些方法在启动或关闭servlet时被容器调用:

public class ChatRoomServer extends SipServlet {

/** Context attribute key to store user list. */

public static String

THE_LIST="https://www.doczj.com/doc/3f12146086.html,erList";

/** Init parameter key to retrieve the chat room's address. */

public static String

THE_NAME="https://www.doczj.com/doc/3f12146086.html,";

/** This chat room server's address, retrieved from the init params. */

public String serverAddress;

/** This is called by the container when starting up the service. */

public void init() throws ServletException {

super.init();

getServletContext().setAttribute(THE_LIST,new

ArrayList());

serverAddress =

getServletConfig().getInitParameter(THE_NAME);

}

/** This is called by the container when shutting down the service. */

public void destroy() {

try

{

sendToAll(serverAddress, "Server is shutting down -- goodbye!");

} catch (Throwable e)

{ //ignore all errors when shutting down.

e.printStackTrace();

}

super.destroy();

}

...

在初始化方法中,我创建了一个所有会话共享的全局属性。这是用户的列表。我还获得了该聊天室的地址(servlet参数)以备将来使用。

2. 消息处理方法

SIP servlet与HTTP servlet稍有不同。对于HTTP servlet,您处理传入的请求,并发送响应消息。而对于SIP servlet,可以发送和接收请求和响应。我将说明如何做到这一点。

当收到消息(请求或响应)时,容器将调用下面的方法。容器将按照下面图表的顺序调用这些方法,也可以重写这些方法来根据消息的类型处理消息:

如果对其进行重写,不要忘记调用super.doRequest()。

其默认实现调用以下方法之一:如果对其进行重写,不要忘记调用sup 其默认实现调用以下方法之一::

下列请求方法之一(自解释):

o doAck(SipServletRequest)

o doBye(SipServletRequest)

o doCancel(SipServletRequest)

o doInfo(SipServletRequest)

o doInvite(SipServletRequest)

o doMessage(SipServletRequest)

o doNotify(SipServletRequest)

o doOptions(SipServletRequest)

o doPrack(SipServletRequest)

o doRegister(SipServletRequest)

o doRequest(SipServletRequest)

o doResponse(SipServletResponse) o doSubscribe(SipServletRequest) 下列响应方法之一:

o doProvisionalResponse(对应于1xx-类响应消息。

o doSuccessResponse(Sip 应于2xx-类响应消息。

o doRedirectResponse(Sip 应于3xx-类响应消息。

o doErrorResponse(SipSe 于4xx-、5xx-以及6xx-类响应消息。

例如,MESSAGE可以调用以下方法:

18. service(),传入一个SipServletRequest(必须进行类型转换)以及

null

19. doRequest()

20. doMessage()

通常只重写最后一级的方法,除非使用了非标准的SIP消息,或者希望收集有关消息的统计信息。

下面是处理即时消息的代码:

/** This is called by the container when a MESSAGE message arrives. */

protected void doMessage(SipServletRequest request) throws

ServletException, IOException {

request.createResponse(SipServletResponse.SC_OK).s end();

String message = request.getContent().toString(); String from = request.getFrom().toString();

//A user asked to quit.

if(message.equalsIgnoreCase("/quit")) {

sendToUser(from, "Bye");

removeUser(from);

return;

}

//Add user to the list

if(!containsUser(from)) {

sendToUser(from, "Welcome to chatroom " + serverAddress +

". Type '/quit' to exit.");

addUser(from);

}

//If the user is joining the chat room silently, no message

//to broadcast, return.

if(message.equalsIgnoreCase("/join")) {

return;

}

//We could implement more IRC commands here,

//see https://www.doczj.com/doc/3f12146086.html,/cmds.html

sendToAll(from, message);

}

* This is called by the container when an error is received

* regarding a sent message, including timeouts.

*/

protected void doErrorResponse(SipServletResponse response)

throws ServletException, IOException {

super.doErrorResponse(response);

//The receiver of the message probably dropped off. Remove

//the receiver from the list.

String receiver = response.getTo().toString(); removeUser(receiver);

}

/**

* This is called by the container when a 2xx-OK message is

* received regarding a sent message.

*/

protected void doSuccessResponse(SipServletResponse response)

throws ServletException, IOException {

super.doSuccessResponse(response);

//We created the app session, we have to destroy it too.

response.getApplicationSession().invalidate(); }

第一个方法在收到一个MESSAGE消息时被调用。最初以一条200 OK消息响应,表明收到了消息。然后它处理服务器命令,比如/join。最后,它调用一个业务逻辑方法来广播传入的消息。

传入的错误响应消息表明上一个请求失败了。这可能意味着有一个用户被断开了。只需将该用户从列表中移除即可。

成功的响应消息表明上一个MESSAGE消息被即时messenger 正确地接收了。因此不再需要该会话,可以将其删除了。通常,

MESSAGE消息是以无状态的形式发送的,并不保存消息之间的连接信息。(对于INVITE消息来说,情况不是这样的,它打开一个有状态的会话直到发送BYE。)

3. 业务逻辑代码

其余的代码由helper方法组成。前两个方法向即时messenger发送消息。要发送消息,使用一个工厂创建以下两项:

o一个SipApplicationSession(稍后将详细介绍)

o一个请求消息

此时,可以随心所欲地修改消息。在我们的例子中,我们在有效负载中添加即时消息文本。最后,发送该消息。

private void sendToAll(String from, String message) throws ServletParseException, IOException { SipFactory factory =

(SipFactory)getServletContext().

getAttribute("javax.servlet.sip.SipFactory");

List list =

(List)getServletContext().getAttribute(THE_LIST);

Iterator users = list.iterator();

while (users.hasNext()) { //Send this message to all on the list.

String user = (String) users.next();

SipApplicationSession session =

factory.createApplicationSession();

SipServletRequest request =

factory.createRequest(session,

"MESSAGE", serverAddress, user);

String msg = from + " sent message: \n" + message; request.setContent(msg.getBytes(),

"text/plain");

request.send();

}

}

private void sendToUser(String to, String message) throws ServletParseException, IOException { SipFactory factory =

(SipFactory)getServletContext().

getAttribute("javax.servlet.sip.SipFactory");

SipApplicationSession session =

factory.createApplicationSession();

SipServletRequest request =

factory.createRequest(session,

"MESSAGE", serverAddress, to);

request.setContent(message.getBytes(),

"text/plain");

request.send();

}

private boolean containsUser(String from) {

List list =

(List)getServletContext().getAttribute(THE_LIST);

return list.contains(from);

}

private void addUser(String from) {

List list =

(List)getServletContext().getAttribute(THE_LIST);

list.add(from);

}

private void removeUser(String from) {

List list =

(List)getServletContext().getAttribute(THE_LIST);

list.remove(from);

}

}

部署描述符

对于HTTP servlet,还必须编写web.xml部署描述符。而在SIP servlet 中,对应的文件是sip.xml,我们在其中列出SIP servlet、初始化参数以及映射(哪个SIP servlet处理哪些SIP消息)。关于该文件语法的更多信息,请参见SIP Servlet规范中15.5节的DTD。其语法类似于web.xml,但

标签除外。它不会将一个URL模式映射到servlet,而是(基于字段和子字段的内容)描述一个条件,SIP请求必须满足这个条件才能被映射到servlet。SIP Servlet规范第11节描述了所有的字段、子字段以及用于该映射的条件。

注意,该映射只用于初始请求;同一个会话/对话中的后续请求由处理初始请求的同一servlet处理。

下面是用于ChatRoomServer的XML代码:

PUBLIC "-//Java Community Process//DTD SIP Application 1.0//EN"

"https://www.doczj.com/doc/3f12146086.html,/dtd/sip-app_1_0.dtd">

ChatRoomServer

相关主题
文本预览
相关文档 最新文档