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

基于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类中添加相应的方法并在应用层调用即可,具有一定的可扩展性。

小米5和MOTOXStyle哪个好小米5和MOTOXStyle哪个好作为小米的全新旗舰,小米5如大家所愿使用了高通的新旗舰骁龙820,并使用了3GLPDDR4UFS2。0等高端硬件,它也是第一个大批量上市开卖的骁龙勿扰模式能打进电话吗手机的勿扰模式其实我们都不怎么用到,基本上这个功能是没落了,但是对于打游戏的人来说,确实很好用。那么,勿扰模式能打进电话吗?下面将会为大家介绍。勿扰模式能打进电话吗在手机开启勿扰模手机正在搜索无服务不能打电话怎么办解决方法很高兴在这里和大家分享维修案例。平时维修中,顾客送修很大一部分是手机无服务正在搜索,手机不能拨打电话,一般都是重摔或者进水导致。信号问题一直困扰着很多维修同行朋友,下面看看这台顾客能打电话的手表几款推荐图文随着科技水平的提高,电子产品越来越多样化。手机不止单一的接电话收短信,而是不断发展到视屏购物转账等等。手表不止单一的报时间,而不断发展到计步,打电话等等的多功能手表。近些年,能打电联想平板s6000报价及功能介绍图文现在,科技越来越发达,电脑也变成了我们生活中必不可少的东西。不管是学习还是娱乐办公,传播信息什么的,都需要电脑。电脑无处不在,能解决许多问题,夺得众多年轻人的喜爱。但是,你真的了解联想s6000平板电脑怎么刷机联想s6000平板电脑刷机步骤盘点出差旅行等长时间的行程中,最让人觉得无聊的恐怕就是在飞机火车上的时间了,所以许多朋友都希望有一款续航功能强大的笔记本电脑,比如说今天我们介绍的这款联想s6000,续航功能很强,是旅联想3300平板电脑评测以及报价解析图解在智能系统的背景下,除了各类智能手机的诞生之外,还有各种各样的平板电脑也在市场上越来越多,与智能手机相比较,平板电脑拥有更流畅的操作和更大的屏幕,体验智能系统的操作将会更加的好,而联想手机多少钱?联想手机价格参考大全现在是手机的时代,是手机解决了人们远程通话聊天的问题,以前没有手机的时候,车马很慢,一封信要送很久才能达到知道对方的消息,但是现在不一样了,现在手机的普遍,让两个很远的人能马上通话lenovo手机大全lenovo手机多少钱图文联想公司是我国知名的民族品牌企业,由于国内厂商还在为争夺市场份额打得头破血流之时,联想公司早已走出国门之外,而且拥有了不错的反响以及广泛的国际知名度。目前大热的智能手机市场联想公司联想笋尖s60怎么样全面评测联想手机是国产手机中销量最好的,因为联想手机的质量很有保障,小编今天推荐的是一款粉嫩的联想手机mdashmdash联想笋尖s60。小编会通过联想s60的配置介绍,以及s60手机的详美图T8s拍照怎么样美图T8s拍照手机开箱图赏9月7日下午,美图在北京正式发布了新一代的T8s拍照手机,这里为大家带来美图T8s拍照手机开箱图赏。美图T8s在硬件方面的表现非常出色,前置配备了双摄像头,可以实现电影级别的虚化美
支付宝上海银行信用卡快捷支付如何开通支付宝上海银行信用卡快捷支付开通方式二在账户通频道开通。上海银行信用卡快捷支付在账户通页面开通方式同招商信用卡快捷支付一致。支付宝(中国)网络技术有限公司是国内领先的独立第三方支付支付宝贵州省农村信用社快捷支付(卡通)是什么支付宝贵州省农村信用社快捷支付(卡通)介绍如下1支持卡种储蓄卡。2签约方式银行柜面(贵州全省)银行网银,3撤销方式银行柜面银行网银。4支付和提现的限额单笔每日累计最高5000元(可支付宝河北银行储蓄卡快捷支付如何撤销支付宝河北银行储蓄卡快捷支付的撤销流程同招商储蓄卡快捷支付一致。支付宝(中国)网络技术有限公司是国内领先的独立第三方支付平台,由阿里巴巴集团创办。支付宝致力于为中国电子商务提供ld支付宝吴江农商银行信用卡快捷支付如何开通支付宝吴江农商银行信用卡快捷支付开通方式二在账户通频道中开通。吴江农商银行信用卡快捷支付在账户通页面开通方式同招商信用卡快捷支付一致。支付宝(中国)网络技术有限公司是国内领先的独立支付宝自贡市商业银行快捷支付(卡通)网银如何查询支付宝自贡市商业银行快捷支付(卡通)网银的查询流程如下登录自贡市商业银行网上银行,点击支付宝签约查询,输入银行卡号,点击查询。支付宝(中国)网络技术有限公司是国内领先的独立第三方支支付宝台州市商业银行卡通如何快捷支付(卡通)(原台州银行)支付宝台州市商业银行卡通快捷支付(卡通)(原台州银行)的方法如下一使用规则1支持卡种大唐卡(储蓄卡)。2办理渠道银行柜面。3限额5000元。4查询余额不支持。5查询限额不支持。6不支付宝渤海银行如何快捷支付(卡通)支付宝渤海银行快捷支付(卡通)的方法如下通知由于双方合作的业务系统升级和改造,渤海银行支付入口暂时关闭,无法使用,开放时间待定。渤海银行快捷支付(卡通)开通方式有两种1网上签约,支支付宝北京银行如何开通网上银行支付宝北京银行开通个人网上银行有三种用户类型证书版网上银行动态密码版网上银行普通版网上银行。可以根据不同版本的安全级别和功能设置进行选择开通和使用,详情可以登录北京银行官方网站查看支付宝青岛银行如何快捷支付(卡通)支付宝青岛银行快捷支付(卡通)的方法如下一使用规则1支持卡种金桥卡(储蓄卡)。2办理渠道网上银行和银行柜面。3支付实时提现限额49999元(可以在网上银行修改支付限额)。4查询余额支付宝如何开通温州银行网上银行支付宝开通温州银行网上银行的方法如下一网上银行申办流程温州银行个人网上银行用户根据其认证方式不同分为专业版网上银行用户(有证书)和大众版网上银行用户(无证书)。用户在营业网点申请注支付宝如何修改工行储蓄卡预留的手机号码支付宝修改工行储蓄卡预留的手机号码的方法如下1携带本人身份证和银行卡到支行级或支行以上的网点,更换手机号。2办理银行ldquo个人客户联系信息查询维护rdquo业务,查询ldquo