loadrunner,socket脚本总结
一、socket脚本编写的基本函数
lrs_startup 初始化 WinSock DLL lrs_create_socket 初始化套接字 lrs_send 在数据报上(UDP)或者向流套接字(TCP)发送数据 lrs_receive 接收来自数据报或流套接字的数据 lrs_close_socket 关闭打开的套接字 lrs_cleanup 终止 WinSock DLL 的使用,回收相关资源。VuGen 在 Windows 上使用 Windows 套接字协议支持应用程序的录制和回放;而在UNIX 平台上仅支持回放 lrs_free_buffer 释放分配给缓冲区的内存 lrs_get_last_received_buffer 获取套接字上接收到的最后的缓冲区及其大小 lrs_get_last_received_buffer_size 获取套接字上接收到的最后一个缓冲区的大小 lrs_set_recv_timeout(param1,param2)第一个参数是s,第二个参数是ms服务器响应超时 lrs_set_recv_timeouts(param1,param2)第一个参数是s,第二个参数是ms匹配收到报文长度
lrs_set_socket_options 设置套接字选项 lrs_set_receive_option 设置套接字接收选项 lrs_save_param将静态或者接收到的缓冲区(或缓冲区部分)保存到参数中 lrs_save_param_ex将用户、静态或接收的缓冲区(或缓冲区部分)保存到参数中 lrs_save_searched_string在静态或接收到的缓冲区中搜索出现的的字符串,将出现字符串的缓冲区部分保存到参数中 |
二、三个关联函数的介绍
lrs_save_param将静态或者接收到的缓冲区(或缓冲区部分)保存到参数中
lrs_save_param_ex将用户、静态或接收的缓冲区(或缓冲区部分)保存到参数中
lrs_save_searched_string在静态或接收到的缓冲区中搜索出现的的字符串,将出现字符串的缓冲区部分保存到参数中
(1) lrs_save_param
lrs_save_param("socket2","buf3","state",172,2);
lrs_save_param("socket2",NULL,"state",172,2);
建议用MULL,表示last receive buffer.
定位172位置的方法:选定buf3后按F7,转换成16进制后,找到你需要的字符,就可以定位了。
lr_error_message("error code is %s",lr_eval_string("<state>"));
Action.c(57): Notify: Saving Parameter "state = AA".
Action.c(58): Notify: Parameter Substitution: parameter "state" = "AA"
Action.c(58): Error: error code is AA
(2)lrs_save_param_ex
例子:lrs_save_param_ex(socketID, "received", Buffer,0,NumberOfBytes, "ascii", "new_parameter");
int lrs_save_param_ex ( char *s_desc, char *type, char *buff, int offset, int length, char *encoding, char *param );
s_desc表示指定的Socket名称;
type表示要存储的数据类型,有“user”、“static”、“received”三种,分别代表用户数据(脚本中自己定义的字符串)、静态数据(data.ws中录制的数据)、最后接收的缓冲区数据;
buff表示要保存哪个缓冲区的数据。这个参数与type有对应关系,如果type是“user”、“static”两种,则需要指定具体的buffer名称;如果是“received”则可以忽略这个参数;
offset表示在buffer中的偏移量;
length表示要从buffer中保存的字节数;
encoding表示的是解码方式。对于“user”类型的buffer,需要指定其为ascii或者ebcdic中的一种,NULL值表示默认的格式为ascii。对于“static”与“received”两种类型的buffer,则可以忽略这个参数,使用客户端的原始编码格式来进行解码;
param表示要保存的参数名称。
(3)lrs_save_searched_string
lrs_save_searched_string ( char* s_desc, char* buf_desc, char* param_name, char* left_boundary, char* right_boundary, int ordinal, int offset, int param_len );
具体参数设置可看F1,帮助文档
lrs_save_searched_string("socket2", NULL, "p", "LB=AAAAAAA\\x01", NULL,1, 0, 2); FAIL
lrs_save_searched_string("socket2", NULL, "p", "LB/BIN=AAAAAAA\\x01", NULL,1, 0, 2);
lrs_save_searched_string("socket2", NULL, "p", "LB/BIN=\\x99\\a", NULL,1, 0, 2);
“\”要转义,并要使用“LB/BIN”不能缺少BIN,左边界出现的次数;offset偏移字节;如果没有右边界则是截长度,否则为-1
小结:
1、 相同点:
三个函数都可以截取报文中的字符串。
2、 三者的区别
(1)lrs_save_param_ex是lrs_save_param的扩展函数,功能相对更全一些,两者均是根据偏移量和查找的数据的长度来定位所需要的数据,所以只适合于返回报文基本固定的情况;
(2)lrs_save_searched_string则是如web脚本里web_reg_save_param,能够根据左右边界灵活处理对于可变返回报文中的字符串;【需注意的是:web_reg_save_param要放在需要关联的请求前,而lrs_save_searched_string是放在请求后】
(3)lrs_save_searched_string函数对于一些特殊情况也是很方便,比如需统计一个字符串总共出现的次数。
三、关于脚本超时相关介绍
socket的脚本里面,我们在LG里面执行到lrs_receive的时候,回放脚本的时候(忽略think time 的情况下)发现脚本回放很慢。但事务的响应时间并不长。在generator的日志里面看到,(Duration: 10.3054 Wasted Time: 10.0000)。其中wasted time为10秒。
这个wasted time 是开销在哪呢?先介绍2个函数:
lrs_set_recv_timeout(param1,param2)第一个参数是s,第二个参数是ms,执行lrs_receive命令后,等待服务器返回消息的超时时间,即服务器的响应时间。
lrs_set_recv_timeout2 创建连接成功,接收到服务器返回的消息后,获取匹配消息的超时时间。lrs_receive接收到数据后,会和预期的数据长度进行比较,如果长度不匹配,它将重新从套接字上读取数据,直到超时为止。
再来看前面的wasted time 就好理解了,在data.ws中recv buf3 4010 ,buf3的长度原本预期为401,录制(或者设置)时接收buffer的大小(4010)和回放时接收的buffer大小预期(401)的不一样,lrs_set_recv_timeout2这个函数就会一直读取缓存区的值,在这里浪费10秒(默认为10秒)。
另外:当我们把这样的脚本放到controller中去执行,执行的结果就是响应时间是正常的,但是TPS很低,原因就是对于这个waiting time,LR并不把这个时间计入到响应时间中,但对于TPS来说,发起的笔数就相对来说少了,这个wasted time 相当于智能的迭代时间。
对于接收报文固定长度的,建议recv buf 长度写成和预期的一致,避免不必要的开销。
但我们也有可能遇到socket返回的响应buffer是变长的, 使用lrs_set_receive_option函数设置返回的属性,来实现这种动态的数据缓冲。
lrs_set_receive_option(EndMarker, EndMarker_None ) // 读取直到缓冲结束.
lrs_set_receive_option(EndMarker, StringTerminator , "\r\n") //读取直到"\r\n"符号出现 .
lrs_set_receive_option(EndMarker, BinaryStringTerminator , "\X00") 读取直到二进制符号"\\X00"出现
此方法适用于知道返回数据包的最后符号的情况,接收过程中读取此符号即停止接收。
2.或者我们手工指定loadrunner脚本,捕获多长的buffer。就需要使用如下代码来代替lrs_receive: lrs_receive_ex("socket1", "buf3", "NumberOfBytesToRecv=150", LrsLastArg); 到此为止,socket通讯单次的发送、接收应该基本没有什么问题了。至于多次交互涉及到的关联等技巧
Another option is mismatch:lrs_set_receive_option(Mismatch,MISMATCH_SIZE)