性能测试函数
1.变量转参数
lr_save_string("参数内容","param"):将字符串“aaa”或者一个字符串变量,转变成LR的参数{param}
2.参数转变量
char var[10];
strcpy(var,lr_eval_string("{param}")):将参数{param}转换成C语言中的变量var
3.取值()
lr_eval_string("{param}"):取出参数{param}中的值,可嵌套在其他函数里使用
4.编码转换函数
lr_convert_string_encoding(lr_eval_string("{msg}"),LR_ENC_UTF8,LR_ENC_SYSTEM_LOCALE,"afterEncodeMsg");
将LR中的参数{msg},从utf-8编码转换为system_local编码(LR本地编码),最后保存到LR的参数{afterEncodeMsg}中
5.参数数组操作
lr_paramarr_random("param_arry"):从参数数组param_arry中随机取一个值,注意param_arry不需要加{}
int size;
size = lr_paramarr_len("param_arry"):获取参数数组param_arry的长度,并保存到C语言的变量size里
int value;
value = lr_paramarr_idx("param_arry",1):获取参数数组param_arry中第1个值,并保存到C语言的变量value里
sprintf(char * string , const char*format_string[,args]) ;将格式化的字符串输出到目标字符串(一般为数组)
strcat(char *dest,char *src);strcat函数会将src所指向的内存空间中的字符连接到dest所指向的内存空间后面
strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL
6.web_url():get接口,详情见帮助文档
7.web_custom_request():post接口,详情见帮助文档(允许您创建一个自定义的 HTTP 请求与任何支持的 HTTP 方法。)
8.atoi(lr_eval_string("{param}")):将LR参数{param}转换为 数字
int itoa ( int value, char *str, int radix );(radix:转换数字时所用的基数 10:十进制;2:二进制…)将数字型转换成字符型
9.web_reg_save_param:关联函数,一定要写在请求之前
10.web_reg_find:文本检查点函数,一定要写在请求之前
11.strcmp(lr_eval_string("{param}"),"str"):将两个字符串类型的变量进行比较,如果相等,返回0,否则,返回1或-1
12.lr_output_message("var"): 输出信息:参数可以是LR参数,c语言变量或者字符串
13.lr_error_message();输入错误的信息
14.web_submit_data(); 提交表单的函数,一般录制时为post请求
WebService接口
1.web_service_call,通过Loadrunner生成
2.lr_xml_get_values,获取服务器返回的xml中指定节点中的内容,并保存成一个参数
3.lr_xml_find,xml检查点,检查服务器返回的xml中有没有指定的内容,并将检查出的结果数量返回回来
Socket接口
1.lrs_create_socket("socket0", "TCP", "RemoteHost=127.0.0.1:8888", LrsLastArg),创建socket连接
2.lrs_send("socket0", "buf0", LrsLastArg),发送buf中的数据
3.lrs_receive("socket0", "buf1", LrsLastArg),接收服务器返回的数据,并保存到一个buf1中
4.lrs_save_param("socket0",NULL,"RecivedData",0,-1),获取服务器返回的数据,并保存到一个参数中RecivedData
5.lrs_save_searched_string("socket0",NULL,"RecivedData","LB/BIN=|","RB/BIN=|",1,0,-1),获取服务器返回的数据,并指定了左右边界
过滤出想要的数据,保存到一个参数中,最后三个参数分别为:取值序号、偏移量、保存长度(右边界不能和lenth同时存在;如果指定了右边界,取值长度必须是-1;如果不指定右边界,可以用NULL代替)
6.lrs_close_socket("socket0"),关闭链接
7.lr_get_vuser_ip,获取该虚拟用户的ip地址
1.web_add_header
1.web_add_header添加HTTP信息头(比如Content-Type,token等)
2. web_custom_request()
2.用web_custom_request()函数实现提交json数据
Method填入相应的请求方式,我这是POST
URL填入请求的地址
Body填入请求的json字符串,此处注意要转义
EncType填入application/json
这样子就可以利用
2.web_reg_save_param
函数名:web_reg_save_param()
1:首先我们通过函数助手:F1键,可以帮我们召唤出函数助手。我们输入web_reg_save_param(),查看这个函数的注释:
函数的作用是从响应结果里面获取指定的内容。
用法:
web_reg_save_param("outFlightVal",
"LB=", "RB=", LAST );
1:LB表示左边界,RB表示右边界
2:这个是预注册函数,顾名思义。如果你要查找指定的字符内容,那么请放在你的请求之前。因为他是从http请求的响应结果里面去查找内容。
3:请自行补充什么是HTTP请求 以及HTTP响应,有助于自己理解第2点内容。
4:什么是左右边界,我们通过如下代码来进行演示:
<meta content="nnMfhFk2-jzizMjXGdiGWSZu8j2sDj5TmDSw" name="csrf-token">
比如说我们要获取‘nnMfhFk2-jzizMjXGdiGWSZu8j2sDj5TmDSw’这段内容,
左边界是:meta content="
右边界是:“name=
5:左右边界一定要是唯一的,这样才能帮我们唯一的找到这个值,否则返回的就是数组类型哦!
实战:
1:地址:http://127.0.0.1:1080/webtours/
2:操作:打开网页,获取登录所需的session
3:因为登录的时候,需要Usersession的内容,我们通过抓包或者是查看源码,可以得到Usersession所在的位置:
<input type=hidden name=userSession value=124084.062616444zDicfHDpQHAiDDDDDicQfpttDicf>
红色的字体部分就是我们所想要的内容。
左边界是:name=userSession value=
右边界是:>
4:脚本如下:
Action()
{
web_reg_save_param("session",
"LB=name=userSession value=",
"RB=>",
LAST);
web_url("web_url",
"URL=http://127.0.0.1:1080/webtours/nav.pl?in=home",
"TargetFrame=",
"Resource=0",
"Referer=",
LAST);
//打印获取到的session值
lr_output_message(lr_eval_string("{session}"));
return 0;
}
5:运行脚本,结果如下所示:
2. 事务
5.web_custom_request
在LR中当使用HTML录制方式时,录制的脚本中主要由函数web_link()、web_submit_form()、web_url()、web_submit_data()组成,当使用HTTP录制方式时,录制的脚本中主要由函数web_url()、web_submit_data()组成,主要区别在于:
当使用HTML录制时得到的函数更接近用户的实际操作,脚本代码相对较少且易于理解一些,但是函数之间有前后依赖关系,耦合度较高,其中web_link()用于模拟用户点击页面上的链接;web_url()用于请求某个链接,Mode的值为HTML,如果某个链接页面上有大量的非html元素,例如:js、css、vbs、activeX、applets、各种格式的图片等,则按照录制时的设置来处理,默认为也录制到脚本步骤中,即web_url()函数的EXTRARES选项中,另外,也可以设置成不录制或录制到并发组web_concurrent_start(NULL)和web_concurrent_end(NULL)之间的web_url()函数中。
当使用HTTP录制时得到的函数将包含所有请求内容,每一项需要请求的内容都会得到一个web_url()函数,Mode的值为HTTP,因此脚本中会有大量的web_url()函数,且一般不带EXTRARES选项,得到的脚本没有很强的前后依赖关系,相对HTMP脚本的耦合度低一些,请求的内容也更全一些,一般只在很标准B/S模式下才会选用HTML,多数时候都可以选用HTTP的方式来录制。另外在该录制模式下,也可以设置选择是否使用并发组函数web_concurrent_start()和web_concurrent_end(),如选择则在很多非HTML的元素的请求前后都会加上并发组函数,还可以选择是否只使用自定义函数web_custom_request(),如选择则得到的脚本中所有的web_url()、web_submit_data()函数都将由函数web_custom_request()替代之。
本文的主角web_custom_request()终于上场了,web_custom_request()函数是一个可以用于自定义http请求的“万能”函数,具有web_link()、web_url()、web_submit_data()函数的功能,一般当自定义请求时可以配合函数web_add_auto_header()、web_add_header()等系列函数来自定义其请求头,web_custom_request()函数的Mode字段为HTML时相当于使用HTML录制方式的函数,Mode字段为HTTP时相当于使用URL录制方式的函数,Method字段可以为GET和POST分别用于模拟http的get和post请求。
该函数web_custom_request()的具体参数说明可以参见本片文章结尾的附录。
当使用web_custom_request()函数来发送http的get和post请求时,如果不使用web_add_header相关函数来自定义添加头部,请求中是否带有默认的头部字段?通过使用抓包工具来查看发出的请求中的头部字段:
脚本一:
web_custom_request("web_custom_request",
"URL=http://www.baidu.com",
"Method=GET",
"TargetFrame=",
"Resource=0",
"Referer=",
"Mode=HTTP",
"Body=123",
LAST);
脚本一实际发出的请求:
GET / HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT)
Accept-Encoding: gzip, deflate
Accept: */*
Connection: Keep-Alive
Host: www.baidu.com
Content-Length: 3
123
脚本二:
web_custom_request("web_custom_request",
"URL=http://www.baidu.com",
"Method=POST",
"TargetFrame=",
"Resource=0",
"Referer=",
"Mode=HTTP",
"Body=abcd",
LAST);
脚本二实际发出的请求:
POST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT)
Accept-Encoding: gzip, deflate
Accept: */*
Connection: Keep-Alive
Host: www.baidu.com
Content-Length: 4
abcd
由此可知,在使用web_custom_request()函数来模拟HTTP请求时,发出的请求中默认带有部分的http请求头部字段,具体字段如上,如需要修改默认的头部字段或增加其他头部字段就在web_custom_request()函数的前面使用web_add_header()函数来添加,如果要减少某个头部字段或全部自动添加的头部字段就在web_custom_request()函数的前面使用web_remove_auto_header()和web_revert_auto_header(),头部字段所有请求中公共的一些头部可以放在web_add_auto_header()函数中,配合web_add_header系列函数来完成自定义的业务脚本。
web_custom_request函数之Body详解:
1. Body:
一般情况下Body中内容是作为字面值进行发送的,Body中也可以发送二进制流(用十六进制表示),方法如下,但仅限二进制流中不含空字符\x00,如果一段Body的二进制流中有空字符,则web_custom_request实际发送的内容为第一个空字符之前的数据,其后的数据(包括空)都会被截断。
例如:
1.1 Body内容不含空字符\x00
1 web_custom_request("web_custom_request",
2 "URL=http://www.baidu.com",
3 "Method=POST",
4 "TargetFrame=",
5 "Resource=0",
6 "Referer=",
7 "Mode=HTTP",
8 "Body=\x3d\x9d\x1d\xef\xa4\x04\x41",
9 LAST);
发送数据包的Body内容为:
1.2 Body内容含空字符\x00
1 web_custom_request("web_custom_request",
2 "URL=http://www.baidu.com",
3 "Method=POST",
4 "TargetFrame=",
5 "Resource=0",
6 "Referer=",
7 "Mode=HTTP",
8 "Body=\x3d\x00\x9d\x1d\xef\xa4\x00\x04\x41",
9 LAST);
发送数据包的Body内容为:
因此使用Body是无法发送含有空的二进制数据流的,此外,Body中的内容可以使用参数替代,web_custom_request函数的整个Body字符串参数("Body=abcd")也是可以使用一个变量(数组或字符指针)来替代的,注意点:1、变量中的内容不需要含有双引号,例如:char BodyVar[20] = "Body=abcd"; 2、使用变量时后面加一个逗号,例如:BodyVar, 。
2. BodyBinary:
当要发送的二进制数据流中含有空时可以使用BodyBinary来发送,注意下面的代码,发送的请求中第一个空之后的数据仍然被截断, 发送数据包的Body内容同1.2中的截图:
1 web_custom_request("web_custom_request",
2 "URL=http://www.baidu.com",
3 "Method=POST",
4 "TargetFrame=",
5 "Resource=0",
6 "Referer=",
7 "Mode=HTTP",
8 "BodyBinary=\x3d\x00\x9d\x1d\xef\xa4\x00\x04\x41\x00\x00\x42",
9 LAST);
正确的写法如下,使用两个转义字符:
1 web_custom_request("web_custom_request",
2 "URL=http://www.baidu.com",
3 "Method=POST",
4 "TargetFrame=",
5 "Resource=0",
6 "Referer=",
7 "Mode=HTTP",
8 "BodyBinary=\\x3d\\x00\\x9d\\x1d\\xef\\xa4\\x00\\x04\\x41\\x00\\x00\\x42",
9 LAST);
也可以如下这样写,只在出现空的地方用两个反斜杠:
1 web_custom_request("web_custom_request",
2 "URL=http://www.baidu.com",
3 "Method=POST",
4 "TargetFrame=",
5 "Resource=0",
6 "Referer=",
7 "Mode=HTTP",
8 "BodyBinary=\x3d\\x00\x9d\x1d\xef\xa4\\x00\x04\x41\\x00\\x00\x42",
9 LAST);
发送数据包的Body内容为:
即二进制数据流中含有空也是可以发送的,上面一栏显示的是八进制表示。BodyBinary中的内容同样可以使用参数替代,整个BodyBinary字符串参数同样可以使用变量替换。如下:
1 char *sendbufhex = "\\x3d\\x00\\x9d\\x1d\\xef\\xa4\\x00\\x04\\x41\\x00\\x00\\x42";
2 lr_save_string(sendbufhex,"sendbufhexParam");
3
4 web_custom_request("web_custom_request",
5 "URL=http://www.baidu.com",
6 "Method=POST",
7 "TargetFrame=",
8 "Resource=0",
9 "Referer=",
10 "Mode=HTTP",
11 "BodyBinary={sendbufhexParam}",
12 LAST);
1 char *sendbufhexBody = "BodyBinary=\\x3d\\x00\\x9d\\x1d\\xef\\xa4\\x00\\x04\\x41\\x00\\x00\\x42";
2
3
4 web_custom_request("web_custom_request",
5 "URL=http://www.baidu.com",
6 "Method=POST",
7 "TargetFrame=",
8 "Resource=0",
9 "Referer=",
10 "Mode=HTTP",
11 sendbufhexBody,
12 LAST);
但是当参数或变量中的内容并不是上面这样直接赋值一个常量字符串,而是通过其他拆分拼接而来时,就只需要使用一个反斜杆,比如:我要发送的的一串二进制流的十六进制字符串为:3d009d1defa4000441000042,参数写法代码如下:
1 char sendbuf[100] ="3d009d1defa4000441000042";
2 char sendbufhex[100];
3 char temp[100];
4 int sendbuflen,i;
5
6 sendbuflen = strlen(sendbuf);
7 memset(sendbufhex,'\0',sizeof(sendbufhex));
8
9 for(i=0;i<sendbuflen;i+=2)
10 {
11 memset(temp,'\0',sizeof(temp));
12 temp[0] = '\\';
13 temp[1] = 'x';
14 temp[2] = sendbuf[i];
15 temp[3] = sendbuf[i+1];
16 lr_output_message("Notify:temp:%s",temp);
17 strcat(sendbufhex,temp);
18 }
19
20 lr_output_message("Notify:sendbufhex:%s",sendbufhex);
21
22 lr_save_string(sendbufhex,"sendbufhexParam");
23
24 lr_output_message("Notify:sendbufhexParam:%s",lr_eval_string("{sendbufhexParam}"));
25
26 web_custom_request("web_custom_request",
27 "URL=http://www.baidu.com",
28 "Method=POST",
29 "TargetFrame=",
30 "Resource=0",
31 "Referer=",
32 "Mode=HTTP",
33 "BodyBinary={sendbufhexParam}",
34 LAST);
特别注意:拼接的参数中只需要一个饭斜杠而不是两个饭斜杠,”3d009d1defa4000441000042" ==》 "\x3d\x00\x9d\x1d\xef\xa4\x00\x04\x41\x00\x00\x42"
变量替换写法代码如下:
1 char sendbuf[100] ="3d009d1defa4000441000042";
2 char sendbufhex[100];
3 char temp[100];
4 int sendbuflen,i;
5 sendbuflen = strlen(sendbuf);
6 lr_output_message("Notify:sendbuflen:%d",sendbuflen);
7
8 memset(sendbufhex,'\0',sizeof(sendbufhex));
9 strcat(sendbufhex,"BodyBinary=");
10
11 for(i=0;i<sendbuflen;i+=2)
12 {
13 memset(temp,'\0',sizeof(temp));
14 temp[0] = '\\';
15 temp[1] = 'x';
16 temp[2] = sendbuf[i];
17 temp[3] = sendbuf[i+1] ;
18 lr_output_message("Notify:temp:%s",temp);
19 strcat(sendbufhex,temp);
20 }
21
22 lr_output_message("Notify:sendbufhex:%s",sendbufhex);
23
24 web_custom_request("web_custom_request",
25 "URL=http://www.baidu.com",
26 "Method=POST",
27 "TargetFrame=",
28 "Resource=0",
29 "Referer=",
30 "Mode=HTTP",
31 sendbufhex,
32 LAST);
3. RAW_BODY
待续...
可用于发送json格式的数据:
1 web_custom_request("request", //随便写个名字
2 "Method=POST", //请求的方法
3 "URL=http://www.baidu.com", //请求地址
4 "RecContentType=application/json", //指定相应头的Content-Type,这里是JSON
5 "EncType=application/json", //指定请求头的Content-Type,这里也是JSON
6 "Mode=HTML",
7 RAW_BODY_START, //请求BODY开始的标识符
8 "{\"userIds\":[1300000001,1300002029,1300003163],\"type\":0}", //BODY的内容
9 55, //上面一行BODY内容的长度
10 RAW_BODY_END, //请求BODY结束的标识符
11 LAST);
实际发送的数据内容为:
web_custom_request函数语法详解
语法:
Int web_custom_request (const char *RequestName, <List of Attributes>,[EXTRARES, <List of Resource Attributes>,] LAST );
返回值:
LR_PASS(0)代表成功
LR_FAIL(1)代表失败。
参数:
1、RequestName:步骤的名称,VuGen中树形视图中显示的名称。
2、List of Attribute:支持的属性有以下几种:
1)URL:
页面地址。
2)Method :
页面的提交方式,POST或GET。
3)EncType:
编码类型。此参数给出一个内容类型(Content-Type),指定其做为回放脚本时“Content-Type”请求头的值,例如“text/html”。Web_custom_request函数不处理未编码的请求体。请求体参数将会使用已经指定的编码方式。因此,如果指定了不匹配HTTP请求体的“EncType”,会引发服务端的错误。通常我们建议不要手动修改录制时的“EncType”值。
任何对于“EncType”的指定都会覆盖web_add_[auto_]header函数指定的Content-Type。当指定了“EncType=”(空值)时,不会产生“Content-Type” 请求头。当省略了“EncType”时,任何一个web_add_[auto_]header函数都会起作用。如果既没有指定EncType也没有web_add_[auto_]header函且“Method=POST”,
“application/x-www-form-urlencoded”会做为默认值来使用。其他情况下,不会产生Content-Type请求头。
4)BodyFilePath:
作为请求体传送的文件的路径。它不能与下面的属性一起使用:Body,或者其他Body属性或Raw Body属性包括BodyBinary,BodyUnicode,RAW_BODY_START或Binary=1。
5)UserAgent:
用户代理,它是一个HTTP头的名字,用来标识应用程序,通常是浏览器,它呈现的是用户和服务器的交互。
例如:头信息“User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)”识别的是Window NT下的IE浏览器6.0。其他的User-Agent的值用来描述其他的浏览器,或者非浏览器程序。通常,一个应用程序中所有的请求都使用相同的用户代理,录制者作为一个运行时参数来指定(Run-Time Setting—Browser Emulation—User Agent)。不管怎么说,即使是在一个简单的浏览器进程中,仍有可能会用到直接与服务器交互的非浏览器组件(例如ActiveX控件),通常他们有着不同于浏览器的用户代理属性。指定“UserAgent”表示这是一个非浏览器的请求。指定的字符串被HTTP头“User-Agent:” 使用,在某些情况下,它同时会影响回放脚本时的行为。例如,不使用浏览器缓存,假设指定的URL属于资源等等。(LoadRunner本身不检查指定的字符串与浏览器本身的值是否相同)
6)Binary:
“Binary=1”表示页面请求体中的每一个以file://x/##形式出现的值(在这里“##”代表2个十六进制数字),都会被替换为单字节的十六进制的值。如果“Binary=0”(默认值),所有的字符序列只是按照字面的值传递。需要注意双斜杠的用法。在C编译器中双斜杠被解释为单斜杠。如果不需要零字节,单斜杠可以在Binary不等于1的情况下使用(例如,使用\x20代替file://x20/)。如果需要零字节,那么只能使用file://x00/且设置 “Binary=1”,\x00在逻辑上会被截断。
7)ContentEncoding
指定请求体的使用指定的方式(gzip或者deflate)进行编码(例如,压缩),相应的“Content-Encoding:” HTTP头会和此请求一起发送。这个参数适用于web_custom_request和web_submit_data。
8)FtpAscii:
“1”使用ASCII模式处理FTP操作;"0" 使用二进制模式。
9)TargetFrame:
当前链接或资源所在Frame的名称。除了Frame的名字,还可以指定下面的参数:
_BLANK:打开一个空窗口。
_PARENT:把最新更改过的的Frame替换为它的上级。
_SELF:替换最新更改过的的Frame。
_TOP:替换整个页面。
10)RecContentType:
录制脚本时响应头的内容类型。例如text/html、 application/x-javascript等。当没有设置Resource属性时,用它来确定目标URL是否是可记录的资源。此属性包含主要的和次要的资源。最频繁使用的类型是 text、application、image。次要的类型根据资源不同变化很多。例如:"RecContentType=text/html":表示html文本。"RecContentType=application/msword":表示当前使用的是Msword。
11)Referer:
当前页面关联的页面。如果已经显式指定了url的地址,此项可以省略。
12)Resource:
指示URL是否属于资源。1 是;0 不是。设置了这个参数后,RecContentType参数被忽略。“Resource=1”,意味着当前操作与所在脚本的成功与否关系不大。在下载资源时如果发生错误,是当作警告而不是错误来处理的;URL是否被下载受“Run-Time Setting—Browser Emulation--Download non-HTML resources” 这个选项的影响。此操作的响应信息是不做为HTML来解析的。“Resource=0”,表明此URL是重要的,不受发送请求(RTS)的影响,在需要时也会解析它。
13)ResourceByteLimit:
web页面下载资源的极限大小。当达到设置的极限后,无法下载其他资源。仅仅对需要下载的资源有效。下载过程:如果总计下载大小小于极限值,则正常开始下载。如果当下载时达到了设置的极限值,资源大小可知(在HTTP响应头中指定了Content-Length),这中情况下,如果只需要一个缓冲区,那么下载可以正常完成。如果需要的不止一个缓冲区,或者资源大小不可知,下载就会中断同时关闭当前连接。这个特性可以用来模拟用户不等待一个页面下载完成时导航到另一个页面的情况。在HTTP模式中无法使用,在Concurrent Groups(Vuser脚本中的一个区,此区中的所有函数并发执行)区中也无法使用。仅仅适用于Sockets的回放,WinInet也是不适用的。
14)Snapshot:
快照的文件名。
15)Mode:
两种录制级别HTML、HTTP。HTML级别--在当前Web界面上录制直观的HTML动作。以一步步的web_url、web_link、web_image、web_submit_form来录制这些动作。VuGen仅仅录制返回HTML页面的请求,不处理脚本和应用程序。HTTP级别--VuGen把所有的请求录制为web_url指令,不生成web_link、web_image、web_submit_form这些函数。这种方法更为灵活,但是生成的脚本不够直观。
16)ExtraResBaseDir:
根URL,放在EXTRARES组里。它是用来解析相对URL的(译者加:类似于Windows的相对路径和绝对路径)。URL可以是绝对路径(例如http://weather.abc.com/weather/forecast.jsp?locCode=LFPO),也可以是相对路径(例如“forecast.jsp?locCode=LFPO”)。真正的URL的下载是通过绝对路径进行的,所以相对URL路径必须使用根路径URL去解析。例如,使用http://weather.abc.com/weather/做为根路径来解析“forecast.jsp?locCode=LFPO”,最后的URL是:http://weather.abc.com/weather/forecast.jsp?locCode=LFPO。如果没有指定“ExtraResBaseDir”,默认的根URL是主页面的URL。
17)Body:
请求体。不同的应用中,请求体分别通过Body、BodyBinary或者BodyUnicode参数来传递。请求体可以只使用其中一个参数,也可以使用一连串的分开的参数组成多请求体。例如:
web_custom_request(
……
"BodyUnicode=REPRICE"
"BodyBinary=\\x08\\x00\\xCC\\x02\\x00\\x00"
"Body=.\r\n"
"-dxjjtbw/(.tp?eg:ch/6--\r\n",
LAST);
在上面的代码中,使用了3个参数来划分请求体,一个是Unicode段,一个是二进制段,最后一个是常规的字符串。最终的请求体是这3个参数按照在函数中的顺序连接起来的值。还有一个很少用到的参数,Binary。它也能描述二进制请求体,但只允许函数中只有一个请求体参数。所有的请求体都是ASCII字符,以null结束。
Body--表示规则的,可打印的字符串。无法表示空字节。所有的字符都以一个反斜杠表示。注意:在旧的脚本中,可以看见不可打印的字符在请求体中以16进制方式进行编码。(例如 “\\x5c”),在这种情况下,必须使用“Binary=1”来标识。空字节使用"file://0.0.0.0/"来表示。 相反,新脚本则会把把请求体分开放在不同的参数中("Body=...", "BodyBinary=...", Body=...")。
BodyBinary--表示二进制代码。不可打印的字符在请求体中以16进制方式file://xhh/进行编码。在这里HH 表示十六进制值。空字节使用"file://0.0.0.0/"来表示。
BodyUnicode--美国英语,特指拉丁UTF-16LE(little-endian)编码。这种编码方式会在在每个字符末尾附加一个0字节,以便使字符更可读。但是在VuGen中实际的参数把所有的0字节都去掉的。但是在发送给Web服务器之前, web_custom_request函数会重新添加0字节的。对于不可打印的字符,使用单反斜杠表示,无法表示空字节。
注意:如果请求体大于100K,会使用一个变量来代替Body参数。变量是在 lrw_custom_body.h中定义的。
18)Raw Body:
请求体是作为指针传递的,此指针指向一串数据。 二进制的请求体可以使用BodyBinary 属性来发送(或者使用Body 属性来传递,前提是必设置
"Binary=1" )。无论如何,这种方法需要使用转义字符反斜杠把不可打印的字符转换为ASCII字符。为了能有一种更简便的表现原始数据的方式,Raw Body属性应运而生,可以传递指向二进制数据的指针。使用4个连续的参数集来表示指针,而且必须按照顺序排列:
RAW_BODY_START
指向数据缓冲区的指针
(int) 长度
RAW_BODY_END
例子:
char *abc= .../* a pointer to the raw data */
web_custom_request("StepName",
"URL=http://some.url ",
"Method=POST",
RAW_BODY_START,
"abc",
3,
RAW_BODY_END,
LAST);
在应用中,即使设置了数据的长度为0,指针也必须有值,不能为空。在“Binary=1”时,不能使用上面的语法传递原始数据。数据缓冲区中的数据不能使用参数化。也就时说,缓冲区中的任何参数(例如 "{MyParam}")不能被正确的替代为相应的值,只会以字面值发送。
3、EXTRARES:表明下面的参数将会是List Of Resource Attributes了。
4、LAST :结尾的标示符。
5、List of Resource Attributes
仅仅当Recording Options--Recording --HTML-based script-- Record within the current script step选项被选中时,List of Resource Attributes才会被插入到代码中。Web页面中的非HTML机制产生了资源列表,包含了Javascript, ActiveX, Java applets and Flash所请求的资源。VuGen's 的Recording 选项中,可以设置把这些资源录制在当前的操作中(默认是此设置)还是作为单独的步骤来录制。
6. lr_convert_string_encoding
lr_convert_string_encoding
//C Language int lr_convert_string_encoding( const char *sourceString, const char *fromEncoding,const char *toEncoding, const char *paramName);官方参数解释:
sourceString
The string to convert
fromEncoding
The encoding of the sourceString
toEncoding
The encoding to convert of the string saved in parameter
paramName
paramName
The name of the parameter in which the destination string will be saved
对应的中文参数解释:
sourceString:被转换的源字符串。
fromEncoding:转换前的字符编码。
toEncoding:要转换成为的字符编码。
paramName:转换后的目标字符串。
lr_convert_string_encoding converts a string encoding betweenthe following encodings: System locale, Unicode, and UTF-8. The function savesthe result string, including its terminating NULL, in the parameter
paramName.
根据上面的说明,这个函数其实只是把字符串在三种编码格式中做转换,所以其实功能也是有限的,不过也已经可以适用到我们常见的一些场景了。
常量和值的对应关系如下:
Possible values for 'fromEncoding'and 'toEncoding' :
Constant
Value
LR_ENC_SYSTEM_LOCALE
NULL
LR_ENC_UTF8
"utf-8"
LR_ENC_UNICODE
"ucs-2"
2.Loadrunner中的使用
在URL请求的返回消息中,我们有时候会遇到中文返回被编码的情况,不易识别,这时候就可以用编码转换函数,方便调试脚本。
————————————————
版权声明:本文为CSDN博主「小英子妮」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/flyaway_07/article/details/50311721
输入值中有中文
Action() { //输入值中有中文
char tmp[50];
lr_convert_string_encoding( lr_eval_string("环球影院"), LR_ENC_SYSTEM_LOCALE, LR_ENC_UTF8, "str" );
lr_log_message("11str is %s",lr_eval_string("{str}")); /* * 据说直接转换过来的内容后面,多了\x00,要通过strcpy函数复制到别的变量后再用,才不受\x00的影响。 */
strcpy(tmp,lr_eval_string("{str}"));
//lr_log_message("str is %s",tmp);
lr_save_string(tmp,"sorvalue"); lr_log_message("str is %s",lr_eval_string("{sorvalue}"));
return 0; } |
2、返回值中有中文
Action2() { // 返回值中有中文
lr_convert_string_encoding( lr_eval_string("鐧戒簯鏈哄満"), LR_ENC_UTF8, LR_ENC_SYSTEM_LOCALE, "strcn" );
lr_log_message("乱码对应的中文是 %s",lr_eval_string("{strcn}"));
return 0; } |
7.lr_eval_string()
函数的主要作用:返回脚本中的一个参数当前的值(从参数中取得对应的值,并且转换为一个字符串)。
格式:lr_eval_string("{参数名}");
例如:lr_eval_string("{parm}");
返回值类型:char
由于返回值类型是char类型,所以可以直接使用lr_output_message(lr_eval_string("{parm}"))函数输出到日志中。
如:lr_output_message(lr_eval_string("{parm}"));
一般多用在调试脚本时输出参数的值.具体用法如下:
lr_output_message("The parameter1's value is %s",lr_eval_string("{parameter1}")),其中参数parameter1在之前已经定义了的参数
lr_log_message(lr_eval_string("{parameter1}"))
改变参数取值的关键在于Select next row和Update value on这两个选项
select next row包含以下选项:
Sequential 顺序取值
Random 随机取值
Unique 唯一取值
Same line as 取某个参数的同行
Update value on 包含以下选项:
Each iteration 每次迭代更新
Each occurrence 每次取值更新
Once 只更新一次
练习
编写一个脚本,并以此脚本为练习的实例:
Action()
{
lr_eval_string("{parameters}");
return 0;
}
parameters的参数值见图
情况一:Sequential 顺序取值+Each
iteration 每次迭代更新
迭代次数为 1
结果为:甲
迭代次数为 2
结果为:甲 乙
迭代次数为 3
结果为:甲 乙 丙
迭代次数为6
结果为:甲 乙 丙 丁 戊甲
扩展:
迭代次数为 1
Action()
{
int i;
for(i=0;i<3;i++)
{
lr_eval_string("{parameters}");
}
lr_eval_string("{parameters}");
return 0;
}
这段执行出的结果为:甲甲甲甲 乙乙乙乙
得出的结论:当使用Update value on + Each iteration时,只有出现了Staring iteration 才会触发记录变化,否则取值内容均不会发生变化。
情况二:Sequential 顺序取值+Each
occurrence 每次取值更新
迭代次数为 1
————————————————
版权声明:本文为CSDN博主「知更鸟的自由」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zgnsjl/article/details/10752501
8. lr_save_string
函数:lr_save_string
定义:将以null结尾的指定字符串保存至参数
函数形式:lr_save_string( const char *param_value, const char *param_name)
示例1:将指定的字符串777 保存至参数textParam.
示例2:将参数textParam的值保存至参数emp_id------可理解为参数复制
Action()
{
lr_save_string("777","textParam");
lr_output_message("textParam的值为:%s",lr_eval_string("{textParam}"));
lr_save_string(lr_eval_string("{textParam}"),"emp_id");
lr_output_message("emp_id的值为:%s",lr_eval_string("{emp_id}"));
return 0;
}
9.strncat()
主要功能是在字符串的结尾追加n个字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
函数说明
编辑
strncat()将会从字符串src的开头拷贝n 个字符到dest字符串尾部,dest要有足够的空间来容纳要拷贝的字符串。如果n大于字符串src的长度,那么仅将src指向的字符串内容追加到dest的尾部。
strncat()会将dest字符串最后的'\0'覆盖掉,字符追加完成后,再追加'\0'。
Output:
Action.c(7): textParam的值为:777
Action.c(11): emp_id的值为:777
123456789101112131415
函数:Sprintf
定义:将格式化的字符串输出到目标字符串(一般为数组)
函数形式:sprintf( char *string_buffer, const char *format_string[, args] );
注:目标字符串需足以容纳格式字符与参数的结果。如果结果字符串长度大于目标字符串,则目标字符串将发生溢出。
示例1:使用 sprintf函数将一个文件的名称写入字符数组(filename)。该文件名称由单词”log”、”下划线”、”i的值”、”点”、”文件后缀”组成.
int index = 56;
char filename[64], * suffix = "txt";
sprintf(filename, "log_%d.%s", index, suffix);
lr_output_message ("The new file name is %s", filename);