文章目录
前言
SIPp是一款功能强大的 SIP 协议性能测试工具,不仅可以模拟 SIP 客户端,也能够模拟 SIP 服务器,还可以通过 XML 场景文件实现测试场景的灵活定制,非常好用。本文主要介绍 SIPp 的入门使用,读者如有兴趣也可以前往 官方传送门 了解更多信息
1. CentOS 环境安装 SIPp
通常在 yum 源比较完备的情况下,执行以下命令即可完成 SIPp 的安装。如果读者无法正常完成安装,建议自行修改添加机器上的 yum 源,例如添加阿里的源,具体做法网上搜索即可,此处不再赘述
sudo yum install sipp -y
2. SIPp 的使用
2.1 常用参数列表
SIPp 常用的参数如下表所示,更多参数可以使用命令 sipp -h 查看详细信息
| 参数 | 功能 | 
|---|---|
| -sn | 使用指定的 SIPp 内嵌的默认场景 | 
| -sd | 导出指定的 SIPp 内嵌场景 XML 文件到当前文件夹 | 
| -sf | 载入使用指定的 XML 场景文件 | 
| -inf | 指定数据配置文件,SIPp 运行时将使用该文件中的数据去填充 XML 场景文件中的占位符 | 
| -s | 指定 SIP 请求的 Resquest-URI 中目标用户的 username 部分,可用于指定被叫号码 | 
| -l | 指定最大同时呼叫数,呼叫总数达到此值时 SIPp 将停止新的呼叫,直到现存呼叫总数低于此值时才继续呼叫 | 
| -r | 指定每秒呼叫数,每秒钟最多呼出的会话数量 | 
| -m | 指定进行 N 次呼叫后停止并退出 | 
| -trace_err | 输出不在 XML 场景文件定义的流程中的、非期望的消息到 < scenario file name >_< pid >_errors.log 文件 | 
| -trace_msg | 输出发送和收到的 SIP 消息到 < scenario file name >_< pid >_messages.log 文件 | 
2.2 使用示例
2.2.1 默认场景使用
- SIP 服务端 UAS 场景
 使用以下命令即可模拟启动一个 SIP 服务端,从界面上可以看到其默认的监听端口为 5060- sudo sipp -sn uas 
- SIP 客户端 UAC 场景
 使用以下命令模拟启动 SIP 客户端,连接本地启动的 UAS 服务端,可以看到 SIP 交互已经开始,基本的呼叫流程打通- sudo sipp -sn uac 127.0.0.1:5060 
2.2.2 内嵌场景文件的配置
SIP 协议呼叫的基本交互流程如下图,不了解的读者可以参考一下,有助于理解下文的场景文件配置。实际上 SIP 是一个类似 HTTP 的文本协议,和 HTTP 一样有着请求方法和响应状态码,读者如有兴趣可自行搜索
- SIP 客户端发送 INVITE 消息,发起一通呼叫
- SIP 服务端收到 INVITE 消息,先响应 100 通知客户端收到请求,接着处理用户呼叫
- SIP 服务端呼叫用户的过程中,响应 180/183 通知客户端呼叫进展
- 被叫用户接通电话后,SIP 服务端响应 200 通知客户端用户已经接通
- SIP 客户端收到消息,发送 ACK 确认通知到 SIP 服务端,主叫用户和被叫用户开始通话
- 被叫用户挂断电话,通话结束,SIP 服务端发送 BYE 消息,结束会话
- SIP 客户端收到 BYE 消息,响应 200 确认会话结束

2.2.2.1 UAC 场景配置文件
- 首先使用以下命令导出 SIPp 内置的 UAC 场景 XML 文件sudo sipp -sd uac > sip-uac.xml
- 点击链接可查看 官网 UAC 场景 XML 文件内容 ,本文不再粘贴。如果读者已经对 SIP 协议的交互有一定了解,那么从中也可以大致理解这个文件配置的流程,比较关键的如下: 
   - XML 配置文件从上到下依次顺序配置了 SIP 交互流程的各个动作,作为主叫方,这里配置的第一个动作是 < send > 标签发起 INVITE 呼叫
- < send > 标签包裹的是将要发给远端的数据,标签属性 retrans配置的是重发间隔,表示如果数据发送失败,500ms 后会重发
- < recv > 标签配置 SIP 客户端期望收到的远端响应信息,其中标签属性 response配置的是 SIP 响应状态码,optional配置预期的响应必要性,默认为 false。如果标签属性optional为 true,表示无论客户端是否收到这个响应都不影响客户端接下来的处理流程;如果为 false,表示如果客户端没有收到期望的响应码,那么 SIP 流程将在此中断,无法继续
- < pause > 标签表示暂停,如果需要指定暂停时长,可以通过这个标签上的 milliseconds属性配置。在 SIP 流程中这个配置相当于模拟双方通话,保持电话不要断开
 

2.2.2.1 UAS 场景配置文件
- 使用以下命令导出 SIPp 内置的 UAS 场景 XML 文件sudo sipp -sd uas > sip-uas.xml
- 官网 UAS 场景 XML 文件内容 和 UAC 配置大同小异,关键点主要如下: 
   - 作为被叫方,这里配置的第一个动作是 < recv > 等待接收客户端的 INVITE 消息
- < recv > 标签配置 SIP 客户端期望收到的远端响应信息,其中标签属性 request配置的是接收到的 SIP 请求方法
 

2.2.3 自定义场景文件使用
SIPp 和具体的 SIP 设备对接的时候,内嵌的默认场景通常很难满足需求,这就需要我们定制修改场景文件。如下是一个定制场景文件并使用的示例,读者可以据此配置自己的场景
- 场景文件定制
 以下是一个笔者用于测试的一个- 定制场景文件 uac_test.xml,该文件从 SIPp 内置的 UAC 场景文件修改而来,关键的点如下,建议读者阅读 官方文档 了解各个标签的功能- 配置文件中使用 [field0]表示第一个占位,该位置将在SIPp启动测试时由指定的数据文件中的数据填充。此处占位符号格式为[fieldN],N 为从 0 开始的整数
- 使用 < nop > 标签配置一个通话过程中执行的 action,此处笔者指定了一个发送 RTP 语音流的动作,流文件为笔者机器当前目录下 test_record.wav,只发送1次,音频编码为 8 (PCMA)
 
 - 需要注意的是,场景配置文件中期望收到的响应要和实际 SIP 交互相契合,少一个响应没有配置上可能就会导致流程异常 - <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE scenario SYSTEM "[field0].dtd"> <scenario name="sip_test"> <send retrans="500"> <![CDATA[ INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[call_number] To: sut <sip:[service]@[remote_ip]:[remote_port]> Call-ID: [call_id] CSeq: 1 INVITE Contact: sip:[field0]@[local_ip]:[local_port] Max-Forwards: 70 Subject: Performance Test Content-Type: application/sdp Content-Length: [len] v=0 o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] s=- c=IN IP[local_ip_type] [local_ip] t=0 0 m=audio [auto_media_port] RTP/AVP 8 a=rtpmap:8 PCMA/8000 a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-11,16 ]]> </send> <recv response="100" optional="true"> </recv> <recv response="180" optional="true"> </recv> <!-- By adding rrs="true" (Record Route Sets), the route sets --> <!-- are saved and used for following messages sent. Useful to test --> <!-- against stateful SIP proxies/B2BUAs. --> <recv response="200" rtd="true" crlf="true"> </recv> <send> <![CDATA[ ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch-4] From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[call_number] To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param] Call-ID: [call_id] CSeq: 1 ACK Contact: sip:[field0]@[local_ip]:[local_port] Max-Forwards: 70 Subject: Performance Test Content-Length: 0 ]]> </send> <nop> <action> <exec rtp_stream="test_record.wav,1,8"/> </action> </nop> <pause milliseconds="25000"/> <!-- The 'crlf' option inserts a blank line in the statistics report. --> <send retrans="500"> <![CDATA[ BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[call_number] To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param] Call-ID: [call_id] CSeq: 3 BYE Contact: sip:[field0]@[local_ip]:[local_port] Max-Forwards: 70 Subject: Performance Test Content-Length: 0 ]]> </send> <recv response="200" crlf="true"> </recv> <!-- definition of the response time repartition table (unit is ms) --> <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> <!-- definition of the call length repartition table (unit is ms) --> <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> </scenario>
- 配置文件中使用 
- 数据文件准备
 在当前目录新建一个- vars.csv文件,文件内容如下,表示顺序读取每一行数据填充到场景配置文件,每一行的数据则根据 PRINTF 指定的总行数动态拼接生成。该配置需要注意以下几点:- 首行申明变量的读取方式及动态生成规则。变量的读取方式包括 3 种:SEQUENTIAL(顺序读取)、RANDOM(随机读取)、USER(基于用户),PRINTF指定动态生成行数
- 其他行对应一次呼叫填充到场景文件的数据。本例中%03d为动态生成数据占位符,如不需要动态生成数据把首行PRINTF去掉,手动填写每一行数据即可 。每一行填充数据使用分隔符;分隔每一项,分隔的项在 XML 场景文件中使用变量名 [filed0],[field1]…[fieldn] 引用
 - SEQUENTIAL,PRINTF=999 1%03d
- 首行申明变量的读取方式及动态生成规则。变量的读取方式包括 3 种:
- 启动测试
 在笔者机器上执行以下命令,启动 SIPp 载入使用定制的- 场景文件 uac_test.xml,- 数据文件 vars.csv模拟 SIP 客户端,以每秒最多呼叫 10 次、最多同时呼叫 10 通会话的频率呼叫测试笔者的 FreeSWITCH 服务器 10.128.39.15:5080 上的 9009 用户- sudo sipp -sf uac_test.xml -inf vars.csv -l 10 -r 10 -trace_msg -trace_err -s 9009 10.128.39.15:5080