sipp

1|0sip介绍

sip - dongye95 - 博客园 (cnblogs.com)

2|0sipp介绍

SIPp是一个测试SIP协议性能的工具软件,它包含了一些基本的SipStone用户代理工作流程(UAC和UAS),并可使用INVITE和BYE建立和释放多个呼叫。它也可以读XML的场景文件,即描述任何性能测试的配置文件。它能动态显示测试运行的统计数据(呼叫速率、信号来回的延迟,以及消息统计)

3|0sipp安装

3|1mac

一键安装

brew install sipp

如果没有 brew 则 根据官网 https://brew.sh/index_zh-cn 教程安装下

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

注意,安装完 brew 之后,需要设置一下 PATH

3|2win

在win上面安装sipp就是在吃屎

3|3Linux

忽略(还没尝试)

3|4安装检测

sipp -v 查看版本号

4|0sipp使用

4|1官方文档

最重要,官方中文文档

https://sipp.sourceforge.net/doc/cn-reference.pdf

4|2初体验

1|0启动内置的uas场景

sipp -sn uas


启动uas后,会在本机开1个端口5061,然后下面会一些SIP信令的实时统计,INVITE文字在“右方向箭头”右侧,表示当前收到的INVITE请求数,180左侧的“左方向箭头”表示回应的振铃消息数。现在只有被叫,并没有主叫来电,所以Messages这一栏全是0

1|0启动内置的uac场景

sipp -sn uac 127.0.0.1:5061

注:最后的“ip:端口”,即为上一步uas启动的ip地址和端口号,必须匹配。


此时,再回到uas的界面,Messages栏,就不再全是0了

这样,主叫方(uac)打电话,被叫方(uas)接电话,基本的呼叫流程就通了。

4|3理解配置文件

直接输入sipp,会看到有很多参数说明,其中-sn 表示加载默认的场景,除了uas/uac,还有regexp/branchc/branchs...等其它场景,有兴趣的同学可以每种场景都试一下。

另外,还有一个很有用的-sd参数,可以把默认的场景配置,直接导出来,参考下面的命令:

这样,就把默认的uac/uas这2个场景,导出成xml文件,方便后续研究。打开这2个文件看一下:

1|0uac.xml

1 <?xml version="1.0" encoding="ISO-8859-1" ?> 2 <!DOCTYPE scenario SYSTEM "sipp.dtd"> 3 4 <scenario name="Basic Sipstone UAC"> 5 <send retrans="500"> 6 <![CDATA[ 7 8 INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0 9 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 10 From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 11 To: [service] <sip:[service]@[remote_ip]:[remote_port]> 12 Call-ID: [call_id] 13 CSeq: 1 INVITE 14 Contact: sip:sipp@[local_ip]:[local_port] 15 Max-Forwards: 70 16 Subject: Performance Test 17 Content-Type: application/sdp 18 Content-Length: [len] 19 20 v=0 21 o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] 22 s=- 23 c=IN IP[media_ip_type] [media_ip] 24 t=0 0 25 m=audio [media_port] RTP/AVP 0 26 a=rtpmap:0 PCMU/8000 27 28 ]]> 29 </send> 30 31 <recv response="100" 32 optional="true"> 33 </recv> 34 35 <recv response="180" optional="true"> 36 </recv> 37 38 <recv response="183" optional="true"> 39 </recv> 40 41 <recv response="200" rtd="true"> 42 </recv> 43 44 <!-- Packet lost can be simulated in any send/recv message by --> 45 <!-- by adding the 'lost = "10"'. Value can be [1-100] percent. --> 46 <send> 47 <![CDATA[ 48 49 ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0 50 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 51 From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 52 To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param] 53 Call-ID: [call_id] 54 CSeq: 1 ACK 55 Contact: sip:sipp@[local_ip]:[local_port] 56 Max-Forwards: 70 57 Subject: Performance Test 58 Content-Length: 0 59 60 ]]> 61 </send> 62 63 <!-- This delay can be customized by the -d command-line option --> 64 <pause/> 65 66 <send retrans="500"> 67 <![CDATA[ 68 69 BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0 70 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 71 From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 72 To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param] 73 Call-ID: [call_id] 74 CSeq: 2 BYE 75 Contact: sip:sipp@[local_ip]:[local_port] 76 Max-Forwards: 70 77 Subject: Performance Test 78 Content-Length: 0 79 80 ]]> 81 </send> 82 83 <recv response="200" crlf="true"> 84 </recv> 85 86 <!-- definition of the response time repartition table (unit is ms) --> 87 <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> 88 89 <!-- definition of the call length repartition table (unit is ms) --> 90 <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> 91 92 </scenario>

看着貌似一大堆,有点吓人,但并不难理解:

  1. 5-29行,第一段send,发送INVITE信令,即:准备打电话
  2. 接下来的31-39行,表示期待收到被叫方回过来的100/180/183响应,注意这3小段,都是optional=true,表示预期的响应是可选的,即:对方可以发100/180/183,也可以不发。通俗点讲,打一通电话过去,对方可能振铃或不振铃(比如:对方已经在通话中,或者话机有问题)
  3. 41行,期待对方回200过来,这里没有optional=true,表示不是可选的,如果收不到,就无法继续。
  4. 46-61行,表示上一步收到200后,主叫方发送ACK确认
  5. 64行,pause暂停,但是并没有指定暂停多久,看注释,可以在启动uac时,传入“-d 暂停时间”指定,这一行相当于电话接起来,模拟双方在通话,让电话先不要断。
  6. 66-81行,表示uac发出bye挂断信令,结束通话,注 retrans="500",表示如果发送失败,500ms后,会重发。

1|0uas.xml

1 <?xml version="1.0" encoding="ISO-8859-1" ?> 2 <!DOCTYPE scenario SYSTEM "sipp.dtd"> 3 4 <scenario name="Basic UAS responder"> 5 6 <recv request="INVITE" crlf="true"> 7 </recv> 8 9 <send> 10 <![CDATA[ 11 12 SIP/2.0 180 Ringing 13 [last_Via:] 14 [last_From:] 15 [last_To:];tag=[pid]SIPpTag01[call_number] 16 [last_Call-ID:] 17 [last_CSeq:] 18 Contact: <sip:[local_ip]:[local_port];transport=[transport]> 19 Content-Length: 0 20 21 ]]> 22 </send> 23 24 <send retrans="500"> 25 <![CDATA[ 26 27 SIP/2.0 200 OK 28 [last_Via:] 29 [last_From:] 30 [last_To:];tag=[pid]SIPpTag01[call_number] 31 [last_Call-ID:] 32 [last_CSeq:] 33 Contact: <sip:[local_ip]:[local_port];transport=[transport]> 34 Content-Type: application/sdp 35 Content-Length: [len] 36 37 v=0 38 o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] 39 s=- 40 c=IN IP[media_ip_type] [media_ip] 41 t=0 0 42 m=audio [media_port] RTP/AVP 0 43 a=rtpmap:0 PCMU/8000 44 45 ]]> 46 </send> 47 48 <recv request="ACK" 49 optional="true" 50 rtd="true" 51 crlf="true"> 52 </recv> 53 54 <recv request="BYE"> 55 </recv> 56 57 <send> 58 <![CDATA[ 59 60 SIP/2.0 200 OK 61 [last_Via:] 62 [last_From:] 63 [last_To:] 64 [last_Call-ID:] 65 [last_CSeq:] 66 Contact: <sip:[local_ip]:[local_port];transport=[transport]> 67 Content-Length: 0 68 69 ]]> 70 </send> 71 72 <!-- Keep the call open for a while in case the 200 is lost to be --> 73 <!-- able to retransmit it if we receive the BYE again. --> 74 <timewait milliseconds="4000"/> 75 76 <!-- definition of the response time repartition table (unit is ms) --> 77 <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> 78 79 <!-- definition of the call length repartition table (unit is ms) --> 80 <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> 81 82 </scenario>
  1. 6-7行,等待主叫方发送INVITE信令。
  2. 9-22行收到主叫方的INVITE请求后,先send 180响应,表示振铃。
  3. 24-46行,发送200 响应,表示被叫方已经ready.
  4. 48-52行,期待对应发过来ACK确认(注:optional=true,表示可选),至此,通话已经建立。
  5. 54-55行,等待被叫方发送挂断信令BYE
  6. 57-70行,发送200,通知主叫方挂断完成。
  7. 74行,等4秒,防止上一步的200响应由于网络原因丢失,留4秒余量,让对方重发BYE信令。

1|0自定义scenario配置

除了内置的几种场景,我们也可以自定义xml配置文件,比如:我们把内置的uas.xml/uac.xml简化一下,让主叫方发起呼叫后,被叫方直接挂断(即:模拟被挂方拒接)

uac2.xml

1 <?xml version="1.0" encoding="ISO-8859-1" ?> 2 <!DOCTYPE scenario SYSTEM "sipp.dtd"> 3 4 <scenario name="Basic Sipstone UAC"> 5 6 <send retrans="500"> 7 <![CDATA[ 8 9 INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0 10 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 11 From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 12 To: [service] <sip:[service]@[remote_ip]:[remote_port]> 13 Call-ID: [call_id] 14 CSeq: 1 INVITE 15 Contact: sip:sipp@[local_ip]:[local_port] 16 Max-Forwards: 70 17 Subject: Performance Test 18 Content-Type: application/sdp 19 Content-Length: [len] 20 21 v=0 22 o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] 23 s=- 24 c=IN IP[media_ip_type] [media_ip] 25 t=0 0 26 m=audio [media_port] RTP/AVP 0 27 a=rtpmap:0 PCMU/8000 28 29 ]]> 30 </send> 31 32 <recv response="200" rtd="true"> 33 </recv> 34 35 <send retrans="500"> 36 <![CDATA[ 37 38 BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0 39 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 40 From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 41 To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param] 42 Call-ID: [call_id] 43 CSeq: 2 BYE 44 Contact: sip:sipp@[local_ip]:[local_port] 45 Max-Forwards: 70 46 Subject: Performance Test 47 Content-Length: 0 48 49 ]]> 50 </send> 51 52 <!-- definition of the response time repartition table (unit is ms) --> 53 <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> 54 55 <!-- definition of the call length repartition table (unit is ms) --> 56 <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> 57 58 </scenario>

uas2.xml

1 <?xml version="1.0" encoding="ISO-8859-1" ?> 2 <!DOCTYPE scenario SYSTEM "sipp.dtd"> 3 4 <scenario name="Basic UAS responder"> 5 6 <recv request="INVITE" crlf="true"> 7 </recv> 8 9 <send retrans="500"> 10 <![CDATA[ 11 12 SIP/2.0 200 OK 13 [last_Via:] 14 [last_From:] 15 [last_To:];tag=[pid]SIPpTag01[call_number] 16 [last_Call-ID:] 17 [last_CSeq:] 18 Contact: <sip:[local_ip]:[local_port];transport=[transport]> 19 Content-Type: application/sdp 20 Content-Length: [len] 21 22 v=0 23 o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] 24 s=- 25 c=IN IP[media_ip_type] [media_ip] 26 t=0 0 27 m=audio [media_port] RTP/AVP 0 28 a=rtpmap:0 PCMU/8000 29 30 ]]> 31 </send> 32 33 <recv request="BYE"> 34 </recv> 35 36 <!-- definition of the response time repartition table (unit is ms) --> 37 <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> 38 39 <!-- definition of the call length repartition table (unit is ms) --> 40 <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> 41 42 </scenario>

使用时,可以用参数-sf加载xml文件

4|4使用数据文件

1|0简单数据文件

测试时,通常需要模拟不同的主被叫号码,前面的测试中,From/To是写死的用户sipp,需要动态替换用户名

SEQUENTIAL #This line will be ignored 1001;1019 1002;1018 1003;1017 1004;1016

创建一个uac_data.csv的文件,内容参考上面。第1行的SEQUENTIAL表示顺序读取,#行表示注释,第3行开始,定义数据行,每行2列,在uac.xml配置文件中,可以用[field0]、[field1]来占位替换,即:

重新跑一下uac场景,这次要新加参数 -inf uac_data.csv,同时为了方便验证SIP报文内容,加上-trace_msg

sipp -sf uac.xml -inf uac_data.csv 127.0.0.1:5060 -trace_msg

跑起来后,应该在当前目录生成类似uac_xxx_messages.log的日志文件,打开看看占位符[field0]/[field1]是否被替换了。

1|0动态数据文件

如果模拟的主/被号很多,一行行手动写有点麻烦,可以用下面的方式自动生成

SEQUENTIAL,PRINTF=999 1%03d;2%03d

其中PRINTF=N,表示生成多少行,而下面的%03d为占位符,真正运行时,会生成

SEQUENTIAL,PRINTF=999 1000;2000 1001;2001 1002;2002 1003;2003 ...

4|5抓包

tcpdump -D会列出本机所有网卡,然后用ifconfig看下各网卡的ip

sudo tcpdump -i en0 port 5070 -vv -w sip_en0.log 抓取网卡en0上,端口号为5070的数据包,并将结果写入sip_en0.log

4|6注册带鉴权


注册CSV脚本

SEQUENTIAL 20000;20000;[authentication username=20000 password=a111111] 20001;20001;[authentication username=20001 password=a111111]
  1. 第一行SEQUENTIAL表示顺序读取
  2. 第二行中每一项使用";"分割,分割的每一项被用于xml文件中的field字段,field字段从0开始编码
  3. 第二项中field1表示的注册域名,不能使用ip地址代替
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE scenario SYSTEM "sipp.dtd"> <scenario name="branch_client"> <label id="1"/> <send retrans="6000"> <![CDATA[ REGISTER sip:[remote_ip] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:5062;branch=[branch] From: <sip:[field0]@[field1]>;tag=[call_number] To: <sip:[field0]@[field1]> Call-ID: [call_id] CSeq: 1 REGISTER Contact: sip:[field0]@[local_ip]:5062 Max-Forwards: 5 Expires: 3600 User-Agent: SIPp Content-Length: 0 ]]> </send> <recv response="401" auth="true"/> <send retrans="6000"> <![CDATA[ REGISTER sip:[remote_ip] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:5062;branch=[branch] From: <sip:[field0]@[field1]>;tag=[call_number] To: <sip:[field0]@[field1]> Call-ID: [call_id] CSeq: 2 REGISTER Contact: sip:[field0]@[local_ip]:5062 [field2] Max-Forwards: 5 Expires: 3600 User-Agent: SIPp Content-Length: 0 ]]> </send> <recv response="200"/> <pause milliseconds="600000" next="1"/> <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> </scenario>

5|0具体细节

recv

<recv request="INVITE" rrs="true" timeout="60000" crlf="true" ontimeout="reRegister"> </recv> 1:recv request="INVITE" 期望收到 INVITE 的 SIP 请求消息 2:rrs="true"路由记录设置,如果该属性被设置为“true”。则收到的消息中的消息头“Record-Route”会被存储,并可以通过[route]关键词调用 3:timeout="60000" 超时时间。除非指定了ontimeout 标否,否则呼叫将被终止 4:ontimeout="reRegister" 在超时之后跳到指定标号 5:crlf="true" 在脚本视图中对应的位置处输出一个空行

暂停

<pause milliseconds = "1000" /> 暂停1秒

send

<send retrans="500"> <![CDATA[ SIP/2.0 200 OK [last_Via:] [last_From:] [last_To:];tag=[pid]SIPpTag01[call_number] [last_Call-ID:] [last_CSeq:] User-Agent: Linephone/3.8.4 (belle-sip/1.4.1) Supported: outbound Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO, UPDATE Content-Type: application/sdp Content-Length: [len] [last_Record-route:] v=0 o=[field0] 53655765 2353687637 IN IP[local_ip_type] [local_ip] s=- c=IN IP[media_ip_type] [media_ip] t=0 0 m=audio [auto_media_port] RTP/AVP 8 101 a=rtpmap:8 PCMA/8000 a=rtpmap:101 telephone-event/8000 ]]> </send> 1:retrans="500" send后没有收到 recv 就每隔500ms 再次发送 2:[last_*] 此关键词用于从接收的上一个 sip 消息中提取指定头域(如果存在)的值。比如[last_to]则表示从接收的上一个 sip 消息中提取 To 域的消息保存到[last_to]中并应用

正则

<recv request="ACK" ontimeout="reRegister"> <action> <ereg regexp=".*" search_in="hdr" header="From:" assign_to="1" /> <ereg regexp=".*" search_in="hdr" header="To:" assign_to="2" /> </action> </recv> 整体的意思,就是在接受到ACK时,把from 头内容存在变量1,to头内容存在变量2 1:在一个“recv”或者“recvCmd”命令中,可以执行一些动作action 2:正则表达式(ereg) 3:regexp 用于使用正则表达式匹配接收到的消息头或者消息体 4:search_in,msg:匹配整个消息,hdr:匹配消息头,body:匹配消息体,var:匹配 SIPp 字符串变量 5:assign_to 将匹配的结果存储到指定单个变量或几个变量,使用$[n]引用变量,可以将变量$[n]的内容应用于 sip 消息或者用于编写 sipp 条件分支脚本。在分配的几个变量中,第一个变 量包含整个正则表达式的内容,接下来的其它变量依次匹配各子正则表达式

变量操作

<nop> <action> <assign assign_to="media_play_count" value="0" /> </action> </nop> 1:nop不对 SIP 协议处理,仅用于执行命令。例:执行播放声音或视频的命令。里面只能跟 action 2:assign_to="media_play_count" value="0" 创建个名为media_play_count的变量,值为0

变量测试

变量测试功能可以用来灵活控制脚本的运行。变量测试的动作命令为“test”,含有四个 参数:variablevalueassign_tocomparevariablevalueassig_to 比较后的结果,variable 是一个布尔值。test 的比较支持 6 种操作,分别为: equal, not_equal, greater_than, less_than,greater_than_equal, 或 less_than_equal

<nop> <action> <test assign_to="2" variable="1" compare="less_than" value="10" /> </action> </nop> 如果$1 比 10 小则设置$2 为真

__EOF__

本文作者😎
本文链接https://www.cnblogs.com/dongye95/p/16894798.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   dongye95  阅读(446)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示