学生实验指导手册(高级)
实验二:软件电话编程实验
【实验名称】
软件电话编程实验。
【实验目的】沈莹
77se通过分析软件电话范例(demo)源代码,了解软件电话的基本功能(如:注册、拨打、 接听、挂断)和扩展功能(铃声设置、音量控制、录音、静音、通话保持、免打扰)的实 现方法。要求学生通过编程实现 demo 代码中未提供的“发送 DTMF”功能,最终达到熟 悉软件电话开发过程的目的。 【背景描述】
小明在 GOOGLE 搜索引擎上输入“软件电话” ,点击“搜索”——“哇,好多,有 SKYPE、SKYPEOUT、Eyebeam 等,估计不下百个” 。 下了几个软件试了一下,可惜,国内软件普遍界面风格比较差,而国外软件又都是英 文界面,郁闷啊… 能不能自己做一个软件电话呢?做一个自己喜欢的界面、符合自己使用习惯的软件电 话呢? 哈,为什么不呢?动手吧!
【实验原理】
本实验通过 windows 标准的 32 位动态链接库(SVCom SDK) ,向 VB、VC++等开 发平台,提供一系列 API(Application Program Interface,应用程序接口)接口函数。通 过在程序中调用这些函数,可以实现软件电话,使其完成注册、拨打、接听和挂断等电话 基本功能,同时还可实现铃声设置、音量控制、录音、静音、通话保持和免打扰等扩展功 能。 通过 API 还可以捕获各种 SIP 响应消息,编写消息处理函数,在应用程序窗口上实现 信息显示、特殊消息处理等功能。 本实验提供的软件电话范例(demo)源代码,就是一个应用程序,在以下的实验中, 将引导大家学习这一程序的工作过程。 第 10 页
共 30 页
学生实验指导手册(高级)
软件电话
SIP 响应消息
接口调用
SVCom SDK
图 2-1
如图 2-1 所示,SVCom SDK 内部封装了 SIP 协议栈和拨号音、铃声等音频管理的实 现细节,向应用程序提供了一系列开发接口,组成一个开发包(SDK) ,而软件电话就是 通过对这个 SDK 的调用实现的。
【实验步骤】
第一步 准备工作
阅读《SVCom SDK 编程指南》 。 准备好开发环境: 安装有 win98 以上操作系统的 PC, 安装 VISUAL C++或者 VISUAL BASIC6 以上开发系统(根据学生学习过的编程语言选用相应的开发系统) 。 Demo 程序提供了基于 VISUAL C++或者 VISUAL BASIC 的两套 project,在开发系 统中打开相应的 project 文件。 在开发环境中导入 DLL 和 LIB 文件到用户工程中。这步操作请仔细阅读《SvCom SDK 编程指南》中“5、Demo 演示说明”之“5.1 DLL 导入”章节。
第二步 阅读 demo 程序,了解软件电话工作的基本流程
1、调用 DLL,开发基本注册功能 在程序中调用 SvComInit 对 DLL 进行初始化,根据返回值判断是否初始化成功,如 果 DLL 已经初始化了,调用该函数会返回 SVCOM_INIT_OK(32) 。 完成对各种消息的处理,建立 DLL 到应用程序的消息循环,包括全局、注册、拨号、 接听、挂断消息。这些消息处理在 VC 中通过 ON_MESSAGE 消息映射实现,在 VB 中通过建立自定义的消息处理函数来实现。 调用 SvComSetParam 设置注册参数。调用该函数后就可以完成对注册和话机相关 参数的设置,如果参数错误,可以通过返回值判断错误的原因所在,然后修改错误 的参数,重新设置参数即可。 调用注册函数 SvComRegister 进行注册,该函数不仅用于第一次注册,可以在更换 注册参数后,例如更换话机号码后用于重新注册新号码。 调用注册函数时,先建立 SIP 协议栈,建立成功后,向用户窗口发送初始化成 功的消息,在 SvComGlobalMsg 中处理该消息,函数返回 0(SIP 初始化成 功) 接下来向服务器发送注册报文, ; 并发送正在注册消息, SvComRegMsg 在 处理消息,函数返回 1(正在 SIP 注册) ,对于 SvComRegister 函数本身返回
第 11 页 共 30 页
气囊学生实验指导手册(高级)
0 (SIP 协议栈对象初始化完成) 再接下来就是发送两次 Register 注册报文到 ; 服务器,如果注册成功,向用户窗口发送注册成功消息,SvComRegMsg 中 处理该消息,函数返回 2(SIP 注册成功) ;
如果注册不成功,就一直不断向 服务器发送注册报文,直到注册超时。 在注册过程中,如果对用户身份鉴权不成功,就会收到服务器发送的 100 Trying 和 401 Unauthorized 响应;在 DLL 内部设定了注册超时时间,在未超 时这段时间,不断发送注册报文,直到超时,提示注册失败;超时以后,SIP 协议栈会自动生成新的注册报文进行下一轮注册。 如果设置的服务器不存在,就不停的发送注册报文;在 DLL 内部设定了注册 超时时间, 在未超时这段时间, 不断发送注册报文, 直到超时, 提示注册失败; 超时以后,SIP 协议栈会自动生成新的注册报文进行下一轮注册。 如果设置的话机密码不正确或者话机号码不存在, 就发送未注册消息到用户程 序窗口,在 SvComRegMsg 处理消息,函数返回 3(未注册:用户名密码校 验失败) 。
2、调用 DLL,开发基本呼叫功能(拨号、接听、挂断) 前提条件 调用 SvComRegister 注册指定号码成功后,就可以进入这一轮环节——话机基本 功能的开发。 拨号 调用函数 SvComMakeCall 拨打指定号码, 首先需要从用户界面上获得用户输入的 电话号码, 判断号码的合法性, 如果合法则开启音频, 接着就向服务器发送 Invite 报文, 邀请对方建立通话; 如果加载了拨号回铃音, 这里可以听到拨号的铃声; 如果对方接听, 则建立通话;如果对方无人接听,则超时一段时候,主动挂断本次呼叫。 注:在拨号(主叫)的时候,当用户发送一个 Invite 建立通话请求到服务器后,服 务器回应 407(需要代理认证)响应消息拒绝这个原始请求。客户端在新一轮的 Invite 请 求 中 增 加 一 个 Proxy-Authenticate 头 域 然 后 再 进 行 身 份 认 证 , Proxy-Authenticate 头域包含了 realm(区域)
的身份认证信息的信任书。 接听 调用函数 SvComAcceptCall 接听来电,如果设定了来电铃声或者自定义铃声,就 会听到相应的铃声,注意,如果两者都设置,这里只播放自定义铃声;如果需要获得来 电号码,就调用函数 SvComGetNumber 获得来电号码;接听来电以后,就与对方建立 通话。 在接听(被叫)的时候,当收到对方的 Invite 请求后,可以选择接听来电或者拒绝 通话; 当接听来电时, 回复一个 200 ok 的响应; 当拒绝来电的时候, 回复一个 486 Busy 的响应。 挂断 调用函数 SvComHangCall 进行拆线。如果话机处于拨号状态,就取消这次拨号; 如果话机处于来电状态,就拒绝来电;如果话机处于通话状态,就挂断这次通话。 挂断通话的一方向对方发送 Bye 的请求, 如果收到 200 ok 的响应就表示挂断成功。
第 12 页
共 30 页
学生实验指导手册(高级)
图 2-2 是几个主要流程的时序图:
鸡西大学学报图 2-2
3、调用 DLL,开发扩展功能(铃声设置、音量控制、录音、静音) 铃声设置 调用函数 SvComSetRi
ng 对铃声进行设置,如果要设置拨号和来电的铃声,首先 在工程中增加两个铃声资源文件 (WAV 文件)然后把资源文件 ID 作为参数传递给 DLL, , 如果 DLL 加载外部资源文件失败,则返回错误的值;如果成功,那么在拨号和来电的 时候就可以听到铃声。 当然也可以设定自定义铃声,铃声文件的格式为 mp3,这样有来电时就播放自定 义铃声,而不再播放来电铃声;如果设置的铃声文件不存在,用户界面窗口会收到播放 失败的消息,此时也不播放来电铃声。 音量控制 调用函数 SvComSetVolume 对系统音量控制面板的音量进行设置,其取值范围 0~65535,可以通过查看音量控制面板进行验证,phoneSize 是对播放设备的波形进行 设置,micSize 是对录音设备的麦克风进行设置,这样就可以对通话过程中的音量进行 控制。
第 13 页 共 30 页
学生实验指导手册(高级)
录音 调用函数 SvComRecord 可以开始录音和停止录音, 这里可以对录音文件的存放路 径进行设置。录音是针对整个通话过程进行的,包括通话双方的声音。 静音 调用函数 SvComSetMute 可以设置静音模式,将话机设置成静音模式以后,我方 可以听到对方的话音,而对方不能听到我方话音。 4、调用 DLL,开发扩展功能(通话保持、免打扰) 通话保持 在通话过程中,调用函数 SvComHold 可以保持住当前通话,中断与对方的通信, 而对方将听到服务器播放的音乐;如果想取消保持住的通
话,需要调用 SvComHold, 参数 bSetCheck 设置为 FALSE 即可。 免打扰 调用函数 SvComSetDoNotDisturb 将话机设置成免打扰状态,如果在来电状态下, 首先拒绝来电, 然后设置成免打扰状态; 如果是其他状态, 直接设置成免打扰状态即可。 这样,任何呼叫都被话机拒绝,在免打扰状态可以调用函数 SvComGetNumber 获得对 方来电的号码。
第三步 了解 DEMO 程序的主界面及实现方法
lancet
拨号示例 首先修改代码 userDlg.cpp 中第 279 的函数: void CUserDlg::OnButtonRegister1() ; 其中调用了 RG-VComDLL API 函数 SvComSetParam()来完成注册的功能,所以 需要手动修改 SvComSetParam 函数的参数,接着开始编译。 运行后,界面如图 2-3:
图 2-3
第 14 页正大传奇
共 30 页