![]() |
|
||||||||||||||
| | 网站首页 | 数据库教程 | web编程 | 服务器 | 程序设计 | | ||
|
||
|
|||||||||||||||||||
| SIP简介,第2部分:SIP SERVLET-----转 | |||||||||||||||||||
作者:佚名 文章来源:不详 点击数: 更新时间:2007-9-12 ![]() |
|||||||||||||||||||
|
SIP简介,第2部分:SIP SERVLET
摘要 会话发起协议(Session Initiation Protocol,SIP)是一个重要的信令协议,它正在迅速被电信业采用以构建下一代应用程序。
简介即时消息传递正在改变人们的生活。它是一个非常有用的工具,结合了电子邮件、Internet电话以及文件传输应用程序的优点。用户甚至可以看到谁在线、谁的状态为“忙碌”。当然了,人们可以用它来长时间地进行不创造任何效益的聊天。但是,员工也可以利用它在老板会见客户时向他发送极为重要的信息。 所以,市场上出现如此多的不同种类的即时消息传递应用程序也就不足为怪了。有这么多的选择应该是一件好事,可是如果员工使用的应用程序与老板使用的不同,那又会怎么样呢?这将是一个大问题,因为这些应用程序大多都使用专有的协议。 SIP为我们带来了福音。SIP很有可能会成为标准的即时消息传递协议。 在本文中,我将开发一个简单的SIP应用程序——一个允许SIP即时messenger (消息传递应用程序)彼此联系并互相传播消息的聊天室服务器端。 SIP SIMPLESIMPLE ,即SIP Instant Messaging and Presence Leveraging Extension(SIP即时消息和现场支持扩展)的缩写,是一个工作组以及一组SIP扩展。其中的一个扩展是MESSAGE消息。可以用它来发送包含文本和二进制内容的任意组合的即时消息。这种消息使用起来非常简单,这也是我决定使用它来开发第一个SIP应用程序的原因。 TextClient为了测试我们的应用程序,我提供了一个小型SIP即时messenger应用程序(参见文章结尾处的“下载”部分)。该应用程序向其他messenger或服务器发送MESSAGE消息。用户界面中包含了客户端的地址、好友地址的输入字段、一个文本消息以及一个提交按钮。图1显示了正在运行的TextClient。
要启动TextClient,只需使用以下命令: java -jar textclient.jar dev2dev.textclient.TextClient username port ChatRoomServer下面是示例应用程序的需求 聊天室是一个虚拟空间,不同的即时messenger应用程序可以在其中进行交互。传入聊天室的消息将向聊天室中其他所有的人进行广播。换句话说,所有的消息都可以被所有用户看到。这意味着,当一个消息到达服务器端应用程序时,用户的地址将被添加到一个列表中。然后消息将被发送到该列表中的所有用户。 此外,还可以实现“命令”。命令以正斜杠(/)开头,它不被广播,而是由服务器自己处理,用于特定功能。我将实现的命令包括:
SIP Servlet APISIP 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个部分组成:
部署描述符对于HTTP servlet,还必须编写web.xml部署描述符。而在SIP servlet中,对应的文件是sip.xml,我们在其中列出SIP servlet、初始化参数以及映射(哪个SIP servlet处理哪些SIP消息)。关于该文件语法的更多信息,请参见SIP Servlet规范中15.5节的DTD。其语法类似于web.xml,但<servlet-mapping>标签除外。它不会将一个URL模式映射到servlet,而是(基于字段和子字段的内容)描述一个条件,SIP请求必须满足这个条件才能被映射到servlet。SIP Servlet规范第11节描述了所有的字段、子字段以及用于该映射的条件。 注意,该映射只用于初始请求;同一个会话/对话中的后续请求由处理初始请求的同一servlet处理。 <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE sip-app PUBLIC "-//Java Community Process//DTD SIP Application 1.0//EN" "http://www.jcp.org/dtd/sip-app_1_0.dtd"><sip-app> <servlet> <servlet-name>ChatRoomServer</servlet-name> <servlet-class>dev2dev.chatroomserver.ChatRoomServer</servlet-class> <init-param> <param-name>dev2dev.chatroomserver.name</param-name> <!-- This will be replaced by the build script --> <param-value>sip:chatroomname@serveraddress</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>ChatRoomServer</servlet-name> <pattern> <and> <equal> <var>request.uri.user</var> <!-- This will be replaced by the build script --> <value>chatroomname</value> </equal> <equal> <var>request.method</var> <value>MESSAGE</value> </equal> </and> </pattern> </servlet-mapping></sip-app> 代码看起来很复杂,其实并非如此。Servlet映射说明了: 如果请求URI的用户名部分等于chatroomname,则将传入的MESSAGE请求映射到ChatRoomServer Servlet。 该聊天室名称只是一个占位符。在编译过程中,会用实际的聊天室名称替换关键字“chatroomname”。 这么做有什么用呢?您可以将同样的服务部署多次,每次都使用其独有的聊天室名称,而消息可以自动发送到相应的servlet。 构建、打包、部署需要对SIP servlet进行编译,并将其打包到SAR(Servlet ARchives)文件中。这些文件在功能上等效于WAR文件,结构也相同。参见图2:
最后一步是部署,这根据SIP应用服务器的不同而不同。通常需要将SAR文件复制到一个部署文件夹中,然后部署应用程序。 下面的Ant脚本可以帮助部署: <project name="ChatRoomServer" default="build" basedir="."> <!-- Change this to specify the name of the chat room. In order to send messages to this chat room, simply deploy just4fun.sar, and use the address sip:just4fun@10.0.2.5060:5060. --> <property name="chatroomname" value="just4fun" /> <!-- Change this to the address and port of the SIP server. --> <property name="serveraddress" value="10.0.2.69:5060" /> <!-- Change this to the location of the SAR deployment folder. --> <property name="sar.deployment" value="" /> <property name="src" value="${basedir}/src" /> <property name="lib" value="${basedir}/lib" /> <property name="tmp" value="${basedir}/tmp" /> <path id="classpath"> <fileset dir="${lib}"/> </path> <target name="build"> <mkdir dir="${tmp}"/> <mkdir dir="${tmp}/WEB-INF"/> <mkdir dir="${tmp}/WEB-INF/classes"/> <mkdir dir="${tmp}/WEB-INF/lib"/> <javac debug="true" srcdir="${src}" destdir="${tmp}/WEB-INF/classes"> <classpath refid="classpath"/> </javac> <copy todir="${tmp}/WEB-INF" file="${basedir}/sip.xml"/> <replace file="${tmp}/WEB-INF/sip.xml" token="chatroomname" value="${chatroomname}"></replace> <replace file="${tmp}/WEB-INF/sip.xml" token="serveraddress" value="${serveraddress}"></replace> <zip destfile="${basedir}/${chatroomname}.sar"> <zipfileset dir="${tmp}"/> </zip> <copy file="${basedir}/${chatroomname}.sar" todir="${sar.deployment}"/> </target></project> 结果聊天室应用程序运行之后,试着通过运行两个TextClient实例来访问它。要确保运行在同一机器上的SIP应用程序使用的是不同的端口。下面的例子显示了运行在同一机器上的3个应用程序:
图3显示了结果。
复杂应用程序我知道本文中的例子相对于我们通常要构建的应用程序来说有点过于简单了,现实中的大多数SIP应用程序都由大量代码组成。 会话和状态:通常,SIP应用程序是一个状态机(state machine),其中呼叫或会话都是长时间保持的(有状态的),直到断开。对于SIP servlet,呼叫是由SipApplicationSession表示的,它可以带属性(状态)。在呼叫中,每个会话(呼叫的分支)由SipApplicationSession中的SipSession表示。(两人间的back-to-back会话要使用一个SipApplicationSession和两个SipSession。会议呼叫可能包含更多的SipSession。这些都可以带属性。容器会根据消息的上下文自动提供相应的会话对象。 分层设计:最糟糕的是将所有的代码放入单个的大型SIP servlet。应该按照相对独立的层来设计复杂的应用程序。一个明显的层就是包括连接池的数据库层。也可以包含一个与SIP信令分离的业务逻辑层。另一个方面是有效负载分析,它应该被构建为一个可重用的层。 其他技术:存在许多先进的SIP servlet技术,包括请求代理、重定向和循环、会话超时管理、身份验证、国际化、TCP支持、计时器、会话监听程序以及错误管理。很明显,本文并没有涵盖所有这些方面,但是您可以在SIP Servlet规范中找到相关内容。 例子:可以参见“参考资料”部分,其中有可以帮助您了解更复杂的SIP编程的例子。 结束语标准促进了互操作性,从而促进了协作。而协作——不管它是用于朋友间的轻松聊天,还是用于重要的文件传输——都是一件好事。 SIP是一个大有前途的电信标准,而SIP Servlet API则是轻松快速地开发服务器端SIP应用程序的极佳方式。在本文中,我们通过一个简单的例子,概述了SIP servlet编程。希望通过本文,能够帮助您在协作的道路上迈出一大步。 下载
参考资料
原文出处:http://dev2dev.bea.com/pub/a/2006/02/sip-servlet.html
本文来源:http://blog.csdn.net/jojobb3138688/archive/2007/09/11/1781464.aspx
|
|||||||||||||||||||
| 文章录入:admin 责任编辑:admin | |||||||||||||||||||
| 【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口】 | |||||||||||||||||||
| 网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!) |
| | 设为首页 | 加入收藏 | 联系站长 | 友情链接 | 版权申明 | 网站公告 | 网站地图 | 管理登录 | | |||
|