范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

基于PJSIP协议栈和Android的VoIP系统设计方案介绍详解

  本文提出一种基于PJSIP协议栈的解决方案,通过Android本地开发工具(NDK),实现一个高效、稳定且功能强大的VoIP系统,具有较高的参考和实用价值。
  1 VoIP设计方案
  1.1 设计目标
  本方案所设计的系统包含以下功能:首先,完成用户终端(如手机)中语音数据的采集与编码,并通过RTP(实时传输协议)/RTCP(RTP传输控制协议)进行传输和控制;其次,完成会话的控制,包括会话的注册、发起、维护与结束、注销等;再次,作为一个应用程序,必须实现一个良好的界面,与用户交互;最后,作为一个开放系统,需具有良好的可扩展性。
  1.2 总体设计
  本方案基本上符合Android的NDK框架的开发规范,将系统分为4层,如图1所示。最上层为应用层,该层将在Android SDK的框架内,采用Java语言来实现;第二层为JNI层,SIP协议栈有很多种实现,其中,采用C语言的SIP协议栈在效率、速度、系统占用方面有着超越其他库(如Java协议栈)的优势,因此,该方案将在第三层采用纯C语言实现的PJSIP协议栈。为了让Java应用层能调用协议栈层,在两层之间需要一个衔接的桥梁,这就是JNI层。最后一层是驱动层,这部分一般是由手机厂商来实现的,本文将不做重点介绍。
  2 VoIP的具体实现
  这里将实现一个完整的VoIP系统,包括协议栈的实现、JNI的编写以及上层UI的设计实现等。
  2.1 SIP协议栈及UA
  SIP协议栈直接关系到整个系统的质量与效率,本文将采用纯C语言开发的PJSIP库。该库采用C语言开发,且源码开放,在兼容性与效率上有明显优势,不仅体积小(完整的SIP封装也不过150 KB),同时还实现了一个内存池,使得安全系数与运行效率大为提高,该系统所采用的就是优化后的PJSIP库。
  2.1.1 PJSIP协议栈
  PJSIP协议栈遵循标准的SIP协议,采用分层架构:SIP/SDP消息编码解析层、传输管理层、SIP终端、事务层、会话层以及应用层等。由于SIP协议采用文本消息发送请求和响应,所以首先需要将SIP消息按照巴斯克范式(ABNF)编码和解析,这就是SIP/SDP消息编码解析层所完成的功能。传输管理层用来管理用户代理与服务器之间的请求和相应;SIP终端是PJSIP中转机制的实现,它主要负责管理各个SIP组建,例如像SIP终端实例注册组件,分发消息到事务层、会话层及应用层,回传处理结果,管理定时器、I/O队列等;事务层通过状态机机制管理SIP信令,每一次状态机状态的改变都将触发回调函数;会话层负责会话的发起与响应,一般与应用层结合在一起,用于用户交互,不同的平台有不同的实现,本文使用Andriod的GUI来实现。
  PJSIP是一个高度封装的库,实际上它是通过PJSUA子库来实现应用的。一个完整的PJSUA生命周期,首先需要初始化,通过函数init()来实现。在这个函数中,将创建代理、初始化变量和堆栈,以及创建一个UDP传输并在最后启动代理;第二步将为UA添加用户,如果需要的话,还要向服务器注册用户;当用户添加成功后,此时可以建立一个呼叫连接,发起会话;当会话连接成功后,就可以使用SRTP协议实时传输加密后的数据,进行通话。最后的过程是挂起或销毁呼叫。
  2.1.2 UA原理
  UA(User Agency)是协议栈的具体实现,PJSIP通过封装了的PJSUA来实现,在这一点上,大部分的SIP库都大同小异,在此将介绍UA的工作原理。
  一个典型的UA包含UAC(User Agency Client)和UAS(User Agency Server)两部分。会话由UAC发起。当呼叫发起时,UAC将首先发送“IN-VITE”消息给SIP代理服务器,服务器收到“INVITE”消息后将返回一个应答“200 OK”,并回答“ACK”进行确认,同时通知主叫用户(即会话发起用户)上线通话。如果主叫端(用户端)主动结束会话,UAC将返回“BYE”消息,同时通知服务器;如果用户端收到服务器传来的“BY-E”消息,回答“200”,并结束会话。
  服务器端,UAS收到UAC(用户端)发来的“INVITE”消息,首先从消息中提取出主、被叫对象,然后检查当前是否有空闲信道,若没有则返回“486 BUSY HERE”(即系统忙)消息;接着将检查被叫用户是否在服务区,如果被叫对象不在服务范围,则返回“404 NOT FOUND”(即用户不在服务区);若被叫用户成功上线,则返回“200 OK”,同时准备开始会话。
  SIP协议栈一般使用SIP统一资源定位符(URL)来标识,它根据URL来寻址,如集群用户“200”,“300”分别对应SIP用户为“200@192.168. 1.100”,“300@192.168.1.100”。本文中也使用这种方式来测试通信。
  2.2 JNI的实现
  PJSIP库和Java类连接是通过JNI来实现的,这也是Android NDK的实现机制,JNI是SUN公司推出的用于Java调用其他语言的接口。
  首先需要一个中间类,这个类中主要建立一些方法用于调用C/C++本地函数。它们的类型均为“publicstatic native int”,以便其他的Java类能够调用。
  2.2.1 新建PJSIP类
  为各个待实现的类新建一个包,可以命名为“com.android.voip.pjsip”,在该包中添加该系统相关的一些类,这些类分别为上节中原理各个步骤的实现。这部分仅仅是为C库的调用提供一个接口,因此具体的实现将放在本地C/C++程序中。
  2.2.2 头文件的生成
  C库与Java间还需通过一个后缀为“.h”的头文件来衔接,这个头文件可以手动编写,也可以通过“Javah”来生成,该工具包含在JDK中,是由SUN公司提供的。
  Javah生产的头文件包含一定的规则,例如,本例中,它将生成的函数声明为“Java_com_android_IMSandroid_pjsip_**”的形式,以便在调用C库时能正确识别。
  由于Java中的数据类型与C/C++不尽相同,因此还必须注意参数传递时参数类型的转换。本文所涉及到的Java数据类型有String和int型,Javah生成的头文件中会先定义好需要传递的参数类型以及函数返回类型,例如方法“add_account(String sip_user,Stringsip_dom-ain,String sip_passwd)”,在头文件中将定义函数的形式为“JNIEXPORT jint JNICALL Java_com_android_IMSandroid_pjsip_add_lac-count(JNIEnv*,jclass,jstring,jstring,jstring)”,其中JNIEXPORT为JNI外部函数声明,jint是“jni.h”中定义C语言中整形的对应类型,JNCALL是JNI关键字。比较特殊的是JNIEnv,它是一个指向类型为JNIEnv_的一个特殊JNI数据结构的指针,它的每个元素都指向一个JNI函数的指针,jclass会根据引用Java类的不同而不同,本文中“pjsip.class”是静态类,因此这里的jclass指的是类本身,如果是非静态类则指的是对象。后面几个就是pjsip类需要传递的参数,根据“jni.h”的定义,String类型对应jstring,int对应jint。然而这只是函数申明与类中方法的形式对应,参数的具体传递还需要相应的转化,具体实现将在下一节详细介绍。
  2.2.3 JNI接口函数的实现
  创建了pjsip库类和头文件之后,必须应用一个库接口函数,这部分是pjsip接口的实现,限于篇幅,本文只讲解几个重要函数的实现。
  (1)init函数
  首先是init函数,对应的接口函数为JNICALL Java_com_android_IMSandroid_pjsip_init。该函数在系统初始化时调用,其作用是配置相关参数,并发起一个pjsua应用。它先通过函数“pjsua_create()”创建一个“pjsua”应用,然后通过三个函数“pjsua_config_default
  (&cfg)”,“pjsua_logging_config_default(&log_cfg”),“pjsua_media_config_default(&media_cfg)”配置其相关参数,其中cfg是pjsua的相关参数,主要是状态改变时的回调函数;log_cfg用来配置log级别;media_cfg中包含时钟频率、声道数目等相关参数。
  完成配置之后就可以使用pjsua_init(&cfg,&log_cfg,&media_cfg)将先前配置的参数初始化。在初始化之后,还需为pjsua添加一个udp传输,这一步是通过pjsua_transport_create(PJSIP_TRANSPORT_UDP,&cfg,NULL)来实现的,cfg中包含指定的通讯端口,3GPP建议使用5060。
  需要注意的是,配置完以上参数之后,还需指定SPEEX编码优先级,一般将其设为最大,可以通过函数pisua_codec_set_priority(&-speex_codec_id,255)来实现。所有配置完成之后,就可以发起pjsua,即最后调用pjsua_start()。成功的话,本函数的返回类型为PJ_SUCCESS。
  (2)make_call函数
  另一个很重要的函数是make_call,其在本接口文件中对应的函数为Java_com_android_IMSandroid_pjsip_make_lcall,这个函数一般在发起会话时调用,它与上一个函数在结构上最大的不同在于本函数需要传递一个字符串参数,前面提到,Java与C/C++在参数结构上并不完全相同,因此这里需要将Java传递过来的String类型的参数转化,可以通过“url_ptr=(char*)env->GetStringUTFChars(url,&iscopy)”来实现。env->GetStringUTFChars在“jni.h”中定义,其功能是将jsting类型(Java)的url复制到char*类型(C)的url_ptr中,以此来完成参数类型的转换。
  为了保证传递地址的有效性,还需要使用pjsua_verify_sip_url(url_ptr)验证,这个函数主要验证url_ptr是符合SIP的规则,即是否是一个合法的SIP地址。然而char*型的地址pjsua中还是不能直接使用的,这是因为pjsua重新封装了参数类型,所以最后还需要将其转化成pj_ str_t类型,pjlib提供pj_str()函数可以完成转化。在完成了参数的转化后,调用“pjsua_call_make_call()”,将发起会话。
  (3)hangup函数和pjsua_destroy函数
  这两个函数用来销毁和挂断会话,一般在需结束的时候调用,它们在接口函数中对应Java_com_android_
  IMSandroid_pjsip_hangup和Java_com_android_IMSandroid_pjsip_destroy,由于没有参数传递,也没有其他的调用,因此这两个函数非常简单,基本上直接调用pjsua提供的pjsua_call_hangup_all()和pjsua_destroy()就能实现。pisua中这两个函数将完成内存释放、账户注销等工作。
  (4)add_account函数
  该函数在基本的pjsua中并不是必须的,但如果要使用SIP服务器的话,就必须实现该函数,它在接口函数中对应“Java_com_android_I-MSandroid_pjsip_add_1account”,同“make_call”一样,也需要传递参数,不同的是,它传递三个参数,只是原理大体一样。
  首先它将参数转化后保持到cfg,通过“pjsua_acc_add(&cfg,PJ_TRUE,&ace_id)”将参数添加到pjsua。pjsua将以其中的sip服务器为目的地址,注册会话发起申请,经过一系列的操作之后,与目的地址发起会话。
  2.2.4 主程序与用户界面
  系统的主程序是一个标准的Android应用程序,它使用Java语言开发,符合SDK规范。与一般的SDK程序不同的是,该类中必须使用Syst-em.loadLibrary加载PJSIP库文件。形式如下:
  System.loadLibrary(“pjsip-jni”);
  其中,pjsip-jni就是上节中PJSIP协议栈生成的库。
  主程序中的基本方式均按照上节中的过程,创建并初始化PJSUA;当call按键被触发时发起会话,调用make-call()方法;当用户接受通话时,点击hang或cancel按键,触发hang()或采用destry()方法等。
  用户接口是通过Android SDK来实现的,这部分几乎全都是Java语言,由于UI不是本文的重点,因此只介绍一个简单的界面,实际应用中用户交互是非常重要的。为了实现所需的功能,至少需要一个文本框来提供SIP地址,以及两个按键来控制会话发起和结束。另外,在呼叫与通话过程中,还需要一个页面来显示,这里可以通过对话框来显示
  3 封装与调试
  为了能在Android平台上方便地使用该系统,在实现了PJSIP协议栈、JNI接口以及UI之后,还需将上面所有的模块进行封装。Android SDK提供了一些很有用的工具,如aapt等,由于本文重点不在AndriodSDK,所以可以采用集成开发工具(如集成在Eclipse中的ADT)来封装。在工程libs(如果不存在则新建)目录下新建一个名为armeabi的目录,将上节生成的.so库文件放到该目录下。ADT在封装资源时会自动将该库文件封装到apk文件中,apk是Android操作系统中应用程序的封装形式,在所有android平台中均能使用。
  封装后安装到Android手机、MID或虚拟机中,并发起会话。与开源SIP软件Linphone通信的结果如图2所示。
  4 结语
  通过测试表明,该系统能够对发起并很好地控制SIP信令,该系统由于采用SIP协议,因此与所有采用这一协议的软件均能通信,如Lin-phone,Kphone等,功能测试中表现良好,实现了VoIP的基本需求。同时如果要增加功能,可以在Java类中添加相应的方法并在应用层调用即可,具有一定的可扩展性。

前锋燃气热水器好不好前锋燃气热水器优点介绍现在我们的市场之所以会有这么多东西,都是因为这些东西能够给我们生活带来好处,比如说冰箱洗衣机暖气片等,这些看似一般般的东西却能给我们带来很多好处。前锋燃气热水器作为热水器的一种,是前锋燃气热水器怎么样前锋燃气热水器优点介绍详解我们都知道,热水器已经成为了新时代的重要家电之一,因为它能够让我们随时使用热水,为我们提供更大的便利,但是市场上各种热水器的品牌很多,质量优劣各异,很多消费者选择的时候都觉得很犹豫万家乐天燃气热水器怎么样万家乐天燃气热水器的品牌介绍热水器渐渐走近人们的生活中,其起着非常重要的作用,人们每天的生活起居都需要热水器,热水器给人们带来了很大的方便。那么热水器就是通过各种物理原理,在一定时间内使冷水温度升高变成热水的万和天燃气热水器品质万和天燃气热水器技术详解燃气热水器是一种技术较为成熟,使用时间比较长的热水器类型,当前生产的品牌非常多,比如万和天燃气热水器在众多的品牌当中,就是具有多方面优势的一个大品牌。万和天然气热水器技术先进,品质天燃气热水器如何安装天燃气热水器安装方法无论是夏天还是冬季,大家对于热水的需求都是很多的,尤其是洗浴的使用,所以很多人都会选择在家庭中安装一款热水器使用,在许许多多的热水器类型中,天燃气热水器是非常不错的一种热水器类型,帅康天燃气热水器优点帅康天燃气热水器怎么样详解在我们的家庭选购热水器的问题上来说,天然气热水器可以说是一款非常不错的产品,而帅康天燃气热水器就是一款在天然气热水器的众多品牌中非常不错的一款,那帅康天燃气热水器使用起来到底怎么样天燃气热水器安装注意什么天燃气热水器安装注意事项在我们的家庭冬季的时候,最经常使用的一种热水设备就是燃气热水器,天燃气热水器因其独特的优势和功能吸引了众多的消费者购买使用,那我们购买了天燃气热水器之后的安装问题该怎么解决呢?所以热水器漏水是什么原因热水器漏水处理方法介绍详解家电多了,问题出的也就频繁了。热水器漏水是很多家庭都会出现的问题,但是根据热水器漏水原因的不同解决方法也不同。下面就跟着小编一起来看一下吧,家居问题,我们一起来解决。热水器漏水解决热水器漏水是什么原因热水器漏水解决方法详细介绍现在家家都有热水器,春夏秋冬洗浴都少不了。可热水器漏水却是一件很糟心的事,那么如果热水器漏水的话,我们该怎么办呢?下面就跟你这小编来具体了解一下热水器内胆漏水的情况及解决方法。热水热水器进水阀门漏水怎么回事导致热水器进水阀门漏水的原因较多,可能是阀门损坏,也可能是阀门接合不牢固等。下面是具体原因和解决方法1可能是热水器进水阀门腐蚀磨损,这种情况需要更换全新的进水阀止水(建议选择全铜材热水器漏水怎么处理热水器漏水处理方法现在的人们越来越重视环保,人们家里都用上了太阳能热水器,热水器也是我们生活中一个必不可少的家电,特别是太阳能热水器,它不仅能够给人们提供生活所需的热水,还非常的环保,但是,家里有热
家用吸尘器如何选购家用吸尘器选购技巧介绍现在用户对吸尘器的需求越来越高了,市场上也相应地推出了更多的吸尘器品牌和型号,很多朋友不知道到底该如何去选择。本篇文章专业介绍了如何选购质量好的家用吸尘器?主要是看吸尘器的电机,看哪款老板吸油烟机好老板吸油烟机怎么样详解对于家庭主妇来说,做饭是很辛苦的事情,特别是做饭时产生的油烟,要是长期吸入的话,对于她们的身体也是有害的。因此精明的家庭主妇都是会选择油烟机的,选择了一台油烟机对于保持我们厨房的整百信吸油烟机好不好百信抽油烟机品牌特点详解说去油烟机啊,这可是人们的好帮手,有了它,我们就不用每天因为打扫厨房的油烟而犯愁了。大家装修厨房的时候,都会选购吸油烟机,市场上的油烟机品牌那么多,大家该怎么选购呢?今天小编给大家百信抽吸油烟机好吗百信抽油烟机性能评测详解说起油烟机啊,这可是人们的好帮手。想当年没有它,我们在厨房里面做饭,那可是被熏得够呛,根本就不想去做饭了。现在有了它,我们就不用每天因为打扫厨房的油烟而犯愁了。但是市场上的油烟机品大信油烟机优点有哪些大信油烟机优点介绍详解厨房是每个女人都会花时间呆的地方,一般人们一日三餐都要在厨房里制作,所以厨房电器中有一样是绝对不能少的,那就是油烟机。没有油烟机的话,会让你的老婆母亲大量接触油烟,既对皮肤不好也对老板吸油烟机怎么样老板吸油烟机介绍图文对于从事装修行业的朋友来讲,都会知道,是家中最脏的地方并不是厕所,而是我们的厨房。因为在平时做饭的过程中会产生大量的油烟,日久天长这些油烟就会附着在墙体表面,十分难以清除。而且大量华为y511怎么样怎么刷机图文教程华为技术有限公司总部位于广东深圳,是一家主要研发生产销售通讯设备的公司,公司成立于1987年,在多年的发展过程中积累了丰富的经验,如今已成为我国电子通讯领域的王牌企业,而华为y51光猫连接无线路由怎么设置?近日在给一个亲戚调试无线路由的时候遇到一个这样的问题,拿出来分享下,也正是这个问题,让我对无线路由有了更深的认识!!!他们原来是通过猫和无线来拨号上网的,搬家后,网线升级到了光纤,tplink路由器怎么修改无线密码tplink路由器修改无线密码方法介绍无线密码是手机笔记本等无线终端连接无线信号时需要输入的无线密码。本文介绍修改(设置取消)无线密码的方法及修改密码后的操作。1登录路由器管理界面电脑通过网线或者无线的方式连接路由器,如何修改无线路由器的密码及WIFI密码修改无线路由器的密码介绍详解如何修改无线路由器的密码以及WIFI密码呢?现在随着互联网时代的来临,让路由器网络以及WIFI成为了我们生活工作环境内的一个组成部分,想要让自己的网络更加安全,修改初始密码是必要的如何修改无线路由器名称随着无线网络的普及,使我们的生活方便了许多,同时也给我们带来了许多的挑战,比如说我是宾馆老板,我想使我的免费WiFi显示我们宾馆的名字,怎么修改路由器的名称呢,路由器密码被盗用,又