毕设之 asterisk

1。Asterisk 体系结构

Asterisk 系统的体系结构非常明晰,他不同于传统的PSTN 交换机,更多的时候,Asterisk 被当做一个连通电话的中间件,Asterisk 的可扩展性使其可以应用的各个领域,基于Asterisk的产品如 trixbox , freeries等,图3.1Asterisk的内核结构。

Asterisk 内核包含了五个必要的核心操作模块和四个可加载的应用接口,它们共同组成了Asterisk的完整结构,五个核心模块分别是:PBX核心模块、动态加载器模块、实时调度和I/O管理器、编解码转换模块和应用启动器模块,四个扩展客家在接口分别是:编码转换接口、Asterisk通道接口(SIP,IAX)、扩展应用接口(AGI,AMI),文件格式接口。

3.1 Asterisk 内核结构

Asterisk基于模块化设计的,通过模块的动态加载实现设定的功能,用户可通过动态加载需要的模块。每当Asterisk启动,动态模块加载器就会加载模块的驱动程序。这些模块包括通道驱动、文件格式、会话记录、编解码器、应用启动器等。

Asterisk 启动后,其PBX核心即启动一个monitor线程监听通道消息,接受并处理通道上的会话请求,这些请求包括会话的初始或通道(Channel)的拆除等。通道接口负责管理会话呼入者的连接状态,无论VOIP连接、PRI连接还是ISDN连接,通道接口会给每一个呼叫的绘画建立一个信道,然后根据需要将这些信达澳彼此相连接,具体的连接细节都将由Asterisk的内核完成。

扩展应用接口允许各式各样的任务模块运行在Asterisk平台上:电话会议、语音信箱、在线数据交换等等。通过这些接口,开发人员可以在电话呼叫的任意阶段与Asterisk交互,可以编写全新的电话应用程序,例如,笔者在开发过程中实现话务员自动报号功能时即在坐席与客户接通时执行一个AGI接口程序,实现向客户报告话务员编号功能。

2 Asterisk内核初始化流程

Asterisk的模块初始化工作由Asterisk 负责,包括系统的启动、初始化各个模块等工作,其中 main()函数是系统的入口,这里负责初始化文件日志系统、设置RTP/RTCP端口、信令通道的初始话(SIP)等, main()函数通过调用load_modules()函数加载各个模块并且注册各个app的入口函数,load_pbx()函数负责加载Asterisk内嵌的函数,它通过读取全局数组builtins中每个app的信息,然后调用ast_register_application注册app的各个入口函数,模块初始化流程如图 3-2 所示。

3.2 Asterisk 模块初始化流程

3 Asterisk 呼叫流程

每一个Asterisk通话都包括一个incoming 连接和一个outbound连接,每个电话都是通过一种通道驱动建立起来的,比如本文开发的系统采用SIP通道,其他通道如ZAP,IAX等,每一类通道驱动都有自己私有的通道数据结构,如SIP通道结构chan_sip ,这些私有的结构从属于一个通用的Asterisk通道数据结构ast_channel

Asterisk 会话建立流程如图3.3 所示。

呼入抵达的场景如下:

1) 呼叫到达监听接口,被某一类通道驱动的接口感知,如 SIP socket.

2) 通道驱动创建一个PBX通道并且为这个通道开启一个PBX线程。

3)执行拨号方案。

4)在这时候至少发生下面其中之一:

a. Asterisk 应答这个呼叫并且播放媒体数据或者读取媒体数据,比如IVR业务。

b.拨号方案促使Asterisk 通过拨号应用函数 Dial 创建一个外呼通道。

5Asterisk 桥接通道,呼叫成功建立

Asterisk 外呼场景如下:

1) Dial创建一个outbound PBX通道并且要求对应的通道驱动创建一个呼叫2)当电话被接通,asterisk桥接媒体流,使得第一个通道的呼叫者能够与 第二路通道的被呼叫者进行通话

3)有些情况下,呼入和呼出的通道使用相同的技术方案和兼容的编解码技术,这时候就会使用本地桥接。这种本地桥接方案中,通道驱动在内部直接传送到来的语音数据到对外的流中,而不通过PBX发送语音帧。

4)如果是SIP协议,将会有一个"external native bridge"asterisk重定向端点,使得语音直接在呼叫者和被呼叫者之间传送。信号被保存下来以方便提供正确的CDR记录。

植入通道(Masquerading channels)

有些情形下,一个通道可能植入到另一个通道中。这种情景在呼叫转移中比较常见,新的通道植入并且接管桥接的工作,旧的通道就成了僵通道而被挂起。

3-3 Asterisk 会话建立流程

4 Asterisk 拨号方案编程

拨号方案是Asterisk系统的核心,因为它定义了Asterisk如何处理来话和去话,拨号方案由指令和步骤序列组成,Asterisk按步骤来执行这些指令。与传统电话系统不同,Asterisk的拨号方案是完全可定制的。

拨号方案由四部分组成:Context, Extensions, PrioritiesApplications.

1) Context

拨号方案被分成几个段,这些成为Context, Context用来对Extension的组命名,它把拨号方案的不同部分进行分离,避免彼此交织在一起,在一个Context 中定义的Extension 完全独立于在另一个Context中定义的ExtensionContext 的表示方法是把名字放在[]中。

2) Extensions

每一个Context 内,可以定义一个或多个ExtensionExtension是要执行的指令,由来电或者通道上所拨的数字来触发。

一个完整的Extension有三个要素:

(1) Extension 的名字或号码。

(2) Priority ,每个扩展可以包含多个步骤,步骤号称作Priority;

(3) Application ,针对呼叫执行的特定动作。

这三个部分用英文逗号分开,如:

Exten => name, priority, application()

下面是笔者开发的系统中拨号方案的一部分,实现语音留言功能

[gfdvoice]

exten => h,1,NoOp(hangup in voicemail)

exten => h,n,Goto(default,h,1)exten => _X.,1,NoOp()

exten => _X.,n,Answer

exten => _X.,n,Set(sound_file=${CUT(sound_file,.,1)})

exten => _X.,n,Playback(${sound_file})

exten => _X.,n,Set(CDR(userfield)=${CDR(userfield)}#rf=${monitor_name})

exten => _X.,n,Set(rcd__start_time=${EPOCH})

exten => _X.,n,Record(${VOICE_MAIL_PATH}/${monitor_name}.wav,5,120)

exten => _X.,n,Set(rcd_end_time=${EPOCH})

exten => _X.,n,playback({monitor_name})

exten => _X.,n,hangup()

到此为止,已经创建了一个简单的拨号方案,呼叫进来时,Asterisk先应答这个呼叫,播放声音文件提示用户留言,接下来开始录音,最终挂断,值得注意的是此拨号方案在用户挂断后可以走到另一个Context,在实际的系统中,此功能用来实现用户挂断后的CDR(呼叫详细记录)生成及短信发送功能。

3.4 Asterisk AGI编程

3.4.1 一个使用AGI 的例子

在具体讲解AGI之前,让我们看一个例子,在此图(3.4)中可以看到AGI在整个呼叫过程中的位置及作用。

3.4 AGI 在呼叫过程中的作用

从图中我们可以看到拨号方案调用一个AGI接口实现查询数据库功能,下面我们再看一段应用AGI的具体代码。

exten => _X.,n,GotoIf($["${web_400}" != "1"]?4:5)

exten => _X.,n,Agi(agi://${AGI_SERVER}:${AGI_PORT}/fs.agi)

上述代码中exten => _X.,n,Agi(agi://${AGI_SERVER}:${AGI_PORT}/fs.agi)AGI的具体调用方式,AGI名字为fs 采用java语言编写。

5AGI介绍

作为Asterisk与外部交互的主要方式,AGI (Asterisk Gateway Interface)提供给开发者强大的功能及灵活性, 利用AGI, 开发者可以采用任何一种编程语言(perl, php, c,java )编写AGI程序与Asterisk交互,Asterisk AGI通过标准输入输出流交换信息,如图3-5所示,Asterisk内部通过输入输出流与外部资源交互信息,实际交互过程中Asterisk 默认给AGI传送相应输入变量,AGI程序接收后处理,返回信息给Asterisk Asterisk通过拨号方案调用AGI,而每一次拨号方案的执行属于一个通道(channel),实际的交互过程为AGI与某一通道交互信息。

3.4 AsteriskAGI交互方式

下面为笔者打开AGI DEBUG 模式下的实际交互过程。

拨号方案为:

exten => _X.,1,Answer

exten => _X.,n,Set(DID=${EXTEN})

exten => _X.,n,Set(CLID=${CALLERID(num)})

exten => _X.,n,AGI(SomeScript.php)

其中exten => _X.,n,AGI(hello.php)AGI的调用。

部分控制台交互过程如下:

AGI Tx >> agi_request: hello.php.php

AGI Tx >> agi_channel: SIP/25946-0821ea88

AGI Tx >> agi_type: SIP

AGI Tx >> agi_extension: 998866015810370728

AGI Tx >> agi_priority: 1

上述控制台信息中,AGI通过标准输入,从Asterisk接收信息,当AGI脚本执行时,Asterisk会向脚本发送各种信息,可以在做其他事情之前通过标准输入获取这些信息,每项数据一行,发送完毕Asterisk会发送一个空行,表示结束,如 AGI Tx >> agi_request: hello.php.php 表示请求的AGI名字。如图 3.5 为具体流程图。

3.5 AsteriskDial plan AGI 交互流程图

6合理使用AGI

虽然使用AGI有很大的灵活性,但是AGI对系统的性能有很大影响,因为Asterisk内部AGI的实现是以进程方式被调用,所以,每调用一次AGI就会创建一个进程,这在大型的呼叫中心系统中对性能影响很大,所以AGI的使用要适当,实际开发过程中AGI主要用来操作数据库以及一些复杂的业务逻辑,笔者在开发系统过程中即采用这种方式,比如呼叫进来后先执行一个agi程序,此程序根据被叫号查询开通此号码的企业,如果企业开通,则取出企业的IVR配置,如采用彩铃还是直播队列等,AGI通过设置企业业务逻辑相关的变量,返回给拨号方案,拨号方案根据这些变量走不同的业务逻辑,如果企业未开通则终止服务并记录呼叫详细记录(CDR),写入数据库。

下面为笔者总结的使用AGI5条原则:

(1) AGI的执行应尽快结束:为了提高系统响应速度,AGI应尽快返回拨号方案。

(2) AGI应用程序中不能有阻塞动作:包括Dial,MeetMe application

(3) 利用Asterisk通道(channel)挂载变量与AGI交互.

(4) 基于虚拟机的语言不适合写AGI程序(fastAGI除外)

(5) 在拨号方案与AGI之间的权衡。

本章介绍了Asterisk系统及其内核,详细讨论了Asterisk编程两大方向,拨号方案及AGI,并列举了笔者开发的系统中的一些例子,从本章我们可以得出结论,Asterisk不但定义了一套完整的体系结构,还提供了丰富的业务扩展能力,Asterisk主要竞争力和核心价值亦体现在此,同时,良好的体系结构使得Asterisk必将是传统PBX的替代品,成为通信领域里程碑式的产品,随着VOIP通信的普及,Asterisk必将展示出更多优秀的技术特性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值