Windows sockets是Windows下的网络编程接口,是一个与网络协议无关的编程接口,几乎所有的网络协议都是它的一个子集。当没有合适的协议来支持当前系统时,Windows sockets作为一种“万能药”,提供了一种基于低层的录制方法。在Windows sockets协议下,任何客户端与服务器之间的交互只是一种发送数据包和接收数据包的过程。
Vuser_init
#include "lrs.h"
vuser_init()
{
lrs_startup(257); //Windows Sockets初始化
//设置Socekt通讯参数
lrs_set_connect_timeout(10,0); //设置连接超时时间
lrs_set_recv_timeout(20,0); //设置服务器响应超时时间
lrs_set_recv_timeout2 (10,0); //设置接收超时时间
return 0;
}
Action
#include "LRPublic_HXB.h" //引用定制开发的LR公用函数库
#include "lrs.h"
char TransName[] ="TransName1"; //事务名称(如果有多个事务可定义多个变量,如TransName1、TransName2)
int RespCodeOff = 437; //响应报文表示交易处理是否成功的响应码的偏移量
char RespCodeSuccess[] = "000000"; //响应报文中表示交易处理正确的响应码内容
char *ActualBuffer; //保存接收数据的内容
int NumberOfBytes; //保存接收数据的大小
int rc; //保存连接成功返回值
Action()
{
//建立Socket连接(对长连接,建立Socket连接放在vuser_init函数中)
rc = lrs_create_socket ("socket0","TCP","RemoteHost=:",LrsLastArg);
if (rc != 0) //建立Socket连接失败时记录错误日志并退出本次迭代
{
lr_error_message("Socekt Connecting Failed”);
return 0;
}
lr_start_transaction(TransName);
//发送请求报文,这里将buf0的内容发送到socket0这个已经声明好的端口中
lrs_send("socket0", "buf0", LrsLastArg); //取缓冲区buf0的报文(已完成参数化数据替换)并发送
lrs_disable_socket("socket0",DISABLE_SEND); //发送完成后禁用socket的发送连接
//该函数将服务器返回的内容保存在buf1中
lrs_receive("socket0", "buf1", LrsLastArg); //对短连接,接收响应报文(异步通讯模式不在此执行receive函数,需要在其他地方接收响应报文)
// lrs_length_receive("socket0", "buf1", OffsetSize, "Size=4", LrsLastArg); //对长连接,获取返回指定长度的响应报文(报文前4个字节表示报文长度,如8583报文)
lrs_get_last_received_buffer ("socket0", &ActualBuffer, &NumberOfBytes); //获取socket0最后收到的buffer和大小
//检查点设置:根据返回响应报文长度及响应码进行判断
if ( NumberOfBytes > 4)
{
//通过响应报文响应码判断事务执行状态(若为查询交易,可再细分查询结果为空的情况,此种情况交易应为成功,但应记录查询结果为空的信息)
if (strncmp(ActualBuffer + RespCodeOff, RespCodeSuccess, sizeof(RespCodeSuccess)-1) == 0){
lr_end_transaction(TransName,LR_PASS);
}else{
lr_end_transaction(TransName,LR_FAIL);
}
}else { //响应报文为空 或 仅收到"0000"心跳信号
lr_end_transaction(TransName,LR_FAIL);
lr_error_message("出错(返回报文为空或仅收到心跳信号)!");
}
lrs_free_buffer(ActualBuffer); //释放ActualBuffer内存空间,否则会引起内存泄露
lrs_close_socket("socket0"); //关闭Socket(对长连接,关闭Socket连接应放在vuser_end函数中)
return 0;
}
Vuser_end
#include "lrs.h"
vuser_end()
{
lrs_cleanup(); //Windows Sockets退出清理
return 0;
}
Windows sockets协议会产生一个data.ws文件,保存所用的传输数据,一般要参数化send中的相关内容
data.ws文件中的recv buf是我们回放脚本时从“Replay Log”中提取的,如果定义的recv buf数和实际响应报文的长度不一致,会发生socket超时,响应时间不准确导致TPS上不去。
完成此协议脚本准备工作
1)IP和PORT
2)请求报文和响应报文规范
3)在响应报文中确定交易的成功码存放的位置
相关函数
Lrs_receive_ex(“socket0”,”buf1”,”NumberOfBytesToRecv=60”,LrsLastArg);
在接受数据包时经常会出现服务端返回的报文长度不定长的问题,如果接收报文长度不相等,LR会等10秒后再接收一次,这样会导致事务莫名奇妙地等待。因为可以根据经验强制批定接收报文长度,避免超时重读的问题。
Lrs_save_param(“socket0”,LRS_LAST_RECEIVED,”result”,10,20);
//lrs_save_param(端口连接名,LRS_LAST_RECEIVED,参数名,偏移量,保存长度);
该函数可以获得服务器返回的内容并保存到一个参数中
Lrs_save_param_ex(“socket0”,”user”,ActualBuffer,302,2,”ascii”,”successcode”);
”user”是将数据保存到参数中的缓冲区类型,”user”为用户缓冲区,”static”为data.ws中的静态缓冲区,”received”为最后接收的缓冲区数据
Lrs_save_searched_string(“socket0”,LRS_LAST_RECEIVED,”result”,”LB=
//Lrs_save_searched_string(端口连接名,LRS_LAST_RECEIVED,参数名,LB=左边界,RB=右边界,取值序号,偏移量,保存长度);
当需要的数据不是固定的位置和长度时,那么就需要通过左右边界的方式来捕获返回值。
Mismatch的匹配机制
Mismatch有两种匹配方式:长度匹配和内容匹配。长度匹配就是当lrs_receive()接收到数据之后就会和我们期望的缓冲区数据进行长度对比,如果实际接收到的数据长度不等于我们期望值,就会报Mismatch错误。
如果我们用lrs_set_receive_option(Mismatch,MISMATCH_CONTENT)来指定匹配方式为内容匹配,那么当lrs_receive()接收到数据之后就会和期望的数据内容进行匹配对比,这时即使长度相同,内容不同也会报Mismatch错误。
回放时出现Mismatch错误不一定意味着回放失败,因为有些返回数据可能含有随机性。
Lrs_set_recv_timeout()与lrs_set_recv_timeout2()
lrs_set_recv_timeout()设置服务器响应超时时间,lrs_set_recv_timeout2 ()设置接收超时时间。如果一个应用程序需要一个较长的时间处理请求,但是一旦处理完毕,服务器就会用很快的速度返回数据。可以用lrs_set_recv_timeout()来设定一个较大的超时时间,而用lrs_set_recv_timeout2()设定一个较小的超时时间来接收数据。而一些应用程序可能连接服务器很快,但是可能由于网络拥堵数据传输会花费比较长的时间,则设置相反。
相关概念
1 同步和异步
同步是发送和接收在同一个链路上;发送一个请求,等待返回,然后再发送下一个请求;可以避免出现死锁,一般共享某一资源的时候用。
异步是两个链路上;发送一个请求,不等待返回,随时可以再发下一个请求,可以提高效率,但必须保证是可以并发处理的;线程安全可使用异步
LR controller收集结果时不能区别同步和异步,Analysis的所有信息都是loadrunner通过自己的计算方法得到的,响应时间即lr_start_transaction()到lr_end_transaction()的时间。
2 短连接和长连接
短连接的过程是:连接->传输数据->关闭连接,如Web网站http服务。短连接将lrs_create_socket()函数和lrs_close_socket()函数放在action中。
长连接的过程是:连接->传输数据->保持连接->传输数据->......->关闭连接,如数据库连接。长连接将lrs_create_socket()函数放在init中,lrs_close_socket()函数放在end中。
3 同步长连接和异步长连接
Socket协议异步长连接性能测试脚本与同步长连接是相同的,只是在统计处理能力和事务平均响应时间方面有区别:TCP同步长连接请求在并发时通过LoadRunner就可以统计TPS和响应时间,而TCP异步长连接方式服务器处理交易请求在大并发压力情况下并不是实时处理的,这就需要到被测系统中的数据库中去统计。
4 单工、全双工和半双工单工:设备中发送器与接收器分工明确,只能由发送器向接收器的单一固定方向上传送数据
全双工:设备既是发送器也是接收器,可以同时在两个方向上传送数据
半双工:同全双工,但某一时刻只能向同一方向传送数据
5 异步双工和异步单工
异步双工:接收和发送在同一程序中,由两个不同的子进程分别负责发送和接收
异步单工:接收和发送是用两个不同的程序来完成