Let's Go!

loadrunner与Winsock协议

上一篇 / 下一篇  2009-05-04 16:13:09 / 个人分类:LoadRunner

lrs_save_param

Saves data from a static or received buffer to a parameter.

intlrs_save_param( char *s_desc,char *buf_desc, char *param_name, intoffset, intparam_len);

s_desc
A descriptor identifying a connected socket.
buf_desc
A descriptor identifying a buffer.
param_name
The name of a parameter to hold the buffer value.
offset
The offset of the data in the buffer to be saved to the parameter.
param_len
The length of the data to be saved to the parameter (in bytes).

Thelrs_save_paramfunction saves data from a buffer to a parameter. This function is used for correlating or linking statements within a script.

The first two parameters specify which buffer to use:

Use a specific buffer from the data file:
Use the last received buffer:
The buffer descriptor has the form. "bufxx"
The socket descriptor is not NULL and the buffer descriptor is NULL
LRS_LAST_RECEIVED is specified as the buf_desc parameter

After specifying an active socket and buffer, you specify a parameter name to store the data. Specify an offset to indicate the offset of the data in the buffer, and length of the data.

Once you save the parameter, you can use it in both the script. and data file. Substitute all of the appropriate constant values with the parameter. Whenever you reference the parameter, enclose it in angle brackets (or other delimiters defined within VuGen options).

Note:To save encoded data from a user buffer to a parameter, use thelrs_save_param_exfunction.

 

 

HP LoadRunner Online Function Reference >Windows Sockets Vuser Functions (LRS)> Example: lrs_save_param

-->

Example: lrs_save_param

In the following example, a user performed a Telnet session. The user used apscommand to determine a process ID (PID), and killed the application based on its PID. Repeating the exact steps during replay will not work—during replay the PID will be different (UNIX assigns a new PID). Killing the PID that was recorded in the script. will be ineffective. To overcome this problem,lr_save_paramsaves the value of the PID to a parameter during replay. This parameter is referenced in the Send buffer which contains thekillcommand.

The following code was recorded. The script. would not perform. the kill command during replay. To correct this, the following steps were performed:

  1. The recorded value of the PID, 28597 was located along with the socket and buffer descriptors. The offset and length of the data was determined. The buffer shown below, buf47, was received after thepscommand. The offset of the PID within the buffer data is 67, and its length is 5.
  2. recv buf47 188 "\r" "\x0" "\r\n""PID TT STAT TIME COMMAND\r\n" "28469 q2 S 0:01 -tcsh (tcsh)\r\n" "28597q2 T 0:00 vi log1.txt\r\n" "28602 q2 R 0:00 ps\r\n" "tears:/tmp_mnt/u/jay>"

    The PID also appeared in the Send buffer, buf48, when the user performed a kill operation to the process.

    send buf48 "kill -928597"

  3. Anlrs_save_paramfunction was placed in the Actions section, before thelrs_sendstatement, in this instance buffer "buf48". NULL was specified in place of a buffer descriptor, indicating that VuGen should use the last received buffer, "buf47". During each subsequent replay, the PID is saved to a parameter calledparam1. The parameter was evaluated and printed in the LoadRunner output window or Application Management agent log file usinglr_output_message.
  4.                      lrs_receive("socket2", "buf47", LrsLastArg);
    lrs_save_param("socket2", NULL, "param1", 67, 5);
    lr_output_message ("param1: %s", lr_eval_string("<param1>"));
    lr_think_time(10);
    lrs_send("socket2", "buf48", LrsLastArg);

  5. The parameter was referenced in the Send buffer in place of the original PID constant. In this example angle brackets were used, but you can define the delimiters from VuGen's Option menu.
  6. send buf48 "kill -9 <param1>"

    Correlating Statements Functions

    Click one of the following functions for more information:

    Saves data from a static or received buffer to a parameter.
    Saves data from a static, received, or user buffer to a parameter.
    Searches for an occurrence of strings in a static or received buffer and saves a portion of the buffer, relative to the string occurrence, to a parameter.
     
     
     


     

     
    [翻译]loadrunner与Winsock协议
    在讨论winsock解决方案之前,我们先讨论一下各种协议是如何工作.从前面的简介可以了解到很多的高级协议,例如FTP,HTTP协议等.
    以及所有基于window的应用(例如IE,WS-FTP)底层都是在Winsocket层上通信,因此任何高级协议的底层都是用Winsocket通信。
        什么时候在LR中选择Winsocket协议呢?你要先了解LR是怎么样工作的:LR捕捉API请求然后再把它们回放。所以当你在
        创建LR WEB脚本的时候,VUGEN捕捉从IE出去的所有的HTTP请求。除此之外lr还支持其他很多协议,例如Oracle,ODBC等。
        在选择不同协议录制脚本的时候,LR是依靠hooks捕捉正确的API请求。所以既然大部分网络协议都是架构在winsocket协议之上的,
        那对于lr不支持的协议,我们都可以在winsocket层上录制脚本。所以当找不到合适协议的时候,可以选择winsocket来录制。
          录制WinSock协议脚本!
          Lr录制新的虚拟用户脚本,选择winsock协议
          在web虚拟用户脚本中录制的是URL信息,所以VUGEN启动流览器并运行就可以了,但选择Winsocket录制的时候,
          可能会是各种形式的应用,并不简简单单就是浏览器,所以在开始的时候我们不需要指定应用的地址。
         下面的例子我们选择winsock来录制web应用,正如上面说的我们开始要指定ie的地址。因为本来lr是支持http协议的,
         所以这个例子并无具体的意义,只是为了使例子简单。
    winsock脚本典型代码?
    lrs_create_socket("socket0", "UDP", "LocalHost=0", "RemoteHost=doors:2084", LrsLastArg);
    lrs_create_socket("socket1", "TCP", "LocalHost=0", "RemoteHost=www2.yahoo.com:80", LrsLastArg);
    lrs_send("socket0", "buf0", LrsLastArg);
    lrs_receive("socket0", "buf1", LrsLastArg);
    lrs_send("socket1", "buf2", LrsLastArg);
    lrs_send("socket0", "buf3", LrsLastArg);
    lrs_receive("socket0", "buf4", LrsLastArg);
    这是访问雅虎的一个应用,正如我们看到的,winsock先打开一个winsocket连接,然后收发包。
    我们发现录制的脚本中比web脚本(三个文件)多一个文件。
          第四个文件是data.ws,它里面记载了在action里面收发所有包的内容。
          下面是一个data.ws的例子。
    send buf0
    "!"
    recv buf1 1
    "!"
    send buf2
    "GET / HTTP/1.1\r\n"
    "Accept: */*\r\n"
    "Accept-Language: en-us\r\n"
    "Accept-Encoding: gzip, deflate\r\n"
    "User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)\r\n"
    "Host:www.yahoo.com\r\n"
    "Connection: Keep-Alive\r\n"
    "Cookie: B=5oj83bst12l6m&b=2; Y=v=1&n=8lln5lmi3f8g1&l=6ef8c0d34b0/o&p=m2a2s"
    "qa4110004&r=3f&lg=us&intl=us; T=z=4TVE6A4ZqE6A9dIIpt30.NQNTYGNDE3NTYwM081&"
    "a=AAE&sk=DAAEwinHlDtEm/&d=c2wBTWpFQk16WXdNakUzTkRneQFhAUFBRQF6egE0VFZFNkFn"
    "V0E-; I=i1=010g1q1u24252e2i2k2p2r494a4g4m4q55565b5g6g6t6u7172737678797a7f7"
    "g7k7n7o888f8k8p8q989c9f9i9k9l9n9qacanapb0b3bdbfbhblbqbrbuc0c1c4cgcmcscteie"
    "jgr&ir=73\r\n"
    "\r\n"
    send buf3
    "!"
    recv buf4 1
    "!"
    recv buf5 2048
    "HTTP/1.0 200 OK\r\n"
    "Content-Length: 16030\r\n"
    "Content-Type: text/html\r\n"
    "\r\n"
    "<html><head><titl
    buf2包含了发给www.yahoo.com的包,buf5包含了从server收到的回应。正如看到的winsock录制的脚本并不像web脚本那样具有可读性,
    因为winsock是我们最后的选择。在buf序列号的后面是buf的字节数。例如5号buffer后面的2048就是表示收到了2048个帧。
       注意:在很多buffer里面你会发现仅仅包含了一个“!”,这是一个网络常识,这个帧对于应用来说没有任何的作用,完全
       可以把这些桢清除掉,在data.ws清除这个帧是效果的,需要到action里把这些桢注释掉。譬如例子中收到和发出的buffer可以用//注释掉。
       这样可以使脚本运行得更快。下边的例子: buffers 0, 1, 3 和 4 可以注释掉:
    lrs_create_socket("socket0", "UDP", "LocalHost=0", "RemoteHost=doors:2084", LrsLastArg);
    lrs_create_socket("socket1", "TCP", "LocalHost=0", "RemoteHost=www2.yahoo.com:80", LrsLastArg);
    // lrs_send("socket0", "buf0", LrsLastArg);
    // lrs_receive("socket0", "buf1", LrsLastArg);
    lrs_send("socket1", "buf2", LrsLastArg);
    // lrs_send("socket0", "buf3", LrsLastArg);
    // lrs_receive("socket0", "buf4", LrsLastArg);
    lrs_receive("socket1", "buf5", LrsLastArg);
    lrs_send("socket0", "buf6", LrsLastArg);
    创建脚本步骤:
    1. VuGen录制脚本
    2.增强脚本
    3.参数化
    4.关联脚本
    5.设置运行参数
    6.运行脚本
    1. VuGen录制脚本
          按照之前章节说的步骤创建脚本,录下来的就是基本脚本,可以先把“!”的buffer注释掉。
    练习:
          创建一个简单的winsock脚本,可以选择MI公司的网站,把录下来的脚本命名为winsocket_1,再用Http协议方式创建一个Web脚本,
          把脚本保存为WebWinsock_1.请不要更改session_id把两种脚本比较,当你登陆的时候,可以收到一个“welcome,jojo....”的消息。
          既然所有的消息都放在data.ws文件里,那么data.ws里面应该能找到这条消息。
    1.1) 在几号bufffer里面包含“welcome,jojo”?怎样判断这是收到的帧而不是发出的帧?还有着个字符串正如显示的那样或者他是html的一个标签。
          仔细查看脚本,在data.ws文件中寻找MSO=SIDxxxxxxxxx,XXXXXX是9位数的号码 ,他表示自从January 1 st,1970以来流逝的所有的秒时间,
          cookie和session_id都是根据时间来生成的,所以脚本里面的9位数也就直接和脚本运行时间挂钩,所以我们要把这个数改成我们每
          次运行脚本的确切时间,首先把这个值更换成参数,在c里面有一个Time()的函数。他返回的就是自从January 1 st,1970以来流逝的所有的秒时间,
          在脚本的开始用这个函数获取时间值
          ,然后把刚才创建的参数指向这个值。然后在data.ws里面替换所有的id,这样每次脚本运行都能获得正确的id。
    1.2)把修改了参数的脚本运行一遍,在脚本的运行日志里面寻找”incorrectly”。会找到"You've reached this page incorrectly"这条消息,
    运行web脚本也会发现类似的消息。其中发生了什么呢?
          注意:在data.ws文件中收到的buffer内容在每次运行时不会改变,录制脚本时data.ws文件被创建并且回放过程中也不会改变?所以lr录制的
          脚本种buffer不是很重要,LR用发送包的数据发出请求,然后对比发送请求的数据包和脚本里面包存的数据,这里lr只判断数据包大小,而不
          是具体内容。如果收到的数据包包括“rob”,而server响应是“bob”,lr也会认为脚本运行成功。但如果server回复的是robot”,这样
          lr就会因为收到包的大小不对而认为脚本执行失败。另一种情况时lr期望收到500bytes大小的包,但是前10秒只收到了100bytes,这时r会认
          为超时判断脚本运行失败,可以通过lrs_set_recv_timeout 函数来设定超时时间。
        那么反面一种情况是,你不想接受所有的数据包,只是想收到包的前100bytes,可以通过函数ltr_receive_ex 来任意设定想要收到的字节。
    2.增强脚本
        在脚本中添加事务,集合点和控制语句等增强脚本,和web脚本不同的是winsock脚本可读性很差,所以要在录制脚本时添加注释,事务和集合点等。
        如果在脚本中有逻辑需求,那么插入逻辑语句 (通用声明不适应Winsock_1脚本).
    3.脚本参数化
          把脚本中变化的值参数化,只要用参数把这些值替换掉就可以,使用不同参数重复业务流程,例如在上面的例子里面jojo/bean就可以参数化
          成为userIDs/passwords
    4.关联脚本
    关联目的是为了让你在一个并发中用到一个商业流程的结果,在web脚本中有这样的过程,从web脚本中sessionid关系到后面的流程能不能运行,
    winsock脚本有同样的问题。所以需要捕获到session id然后把它关联起来,举个例子从下面的脚本中获取PID(lr函数的例子):
    "\r"
    "\x0 blah blah blah "
    "\r\n blah blah blah "
    "PID TT STAT TIME COMMAND\r\n PID 28469 q2"
    " S 0:01 -tcsh (tcsh)\r\n"
    在一个典型的web脚本中,你用web_create_html_param函数,用“PID“ 和“q2”定义边界扑获数据。
    在Winsock脚本中,用lrs_save_param函数从静态数据或收到的数据包中截获数据,看下面的例子:
    lrs_receive("socket2", "buf47", LrsLastArg);
    lrs_save_param("socket2", NULL, "param1", 67, 5);
    和web_create_html_param函数不同的是lrs_save_param在请求之后进行,这个例子中,第一行代码是接收到47号包。lrs_save_param函数的参数意义如下:
    socket2: 从socket2中扑获数据
        NULL: null参数意思是从最后一个buffer里截取,在这儿就是指buf47,如果你从其它的buf里面来获取数据,则你必须要指明buf的号码了
    param1:命名的参数值
    67:位移(下面截解释)
    5:捕获的长度
    位移:从buffer的开始多少位去捕获参数的值,在下面的例子里面,PID是从buf47开始往后67bytes来截取的,我们怎么确定这个值?
    在data.ws中选取需要截取参数的地方然后按F7键,这样会弹出一个窗体。如下图:
    在左边的列,你将看到符合这部分数据的偏移量,中间四行是用EBCDIC加密的数据包。最右边,是没有经过加密的数据。所以你应该看第五行
    包含PID的真实的数据,,很容易就可以根据64+3得出位偏移为67。
    (现在我们解释一下问什么添加这些多余的东西到数据包中,让它适合我的例子呢?)
    注意:在socket脚本中没有提供web_find函数。只有通过编程来找到你要截取的脚本。
    5.run-time的设置
    配置Run-Time可以控制脚本运行过程中的虚拟用户行为,包括loop,log和Time信息等设置
    6.VuGen运行脚本.
    保存并用VuGen运行脚本验证脚本是否正确
    搞定WinSock!
     
    =============================================== 
    实例:
    #include "lrs.h"
    int rc;
    Action()
    {
    
        lr_think_time(8);
    
        lrs_send("socket0", "buf0", LrsLastArg);
    
        lrs_receive("socket0", "buf1", LrsLastArg);
    
            lrs_save_param("socket0", "buf1", "param1", 6, 11); 
    
            rc = strcmp("<param1>","<param2>");
    
            if(rc != 0)
            {
            lr_error_message ("error:data != %s", lr_eval_string("<param1>"));        
    
            //return -1;
            }
            else return 0;
    }
     
    winsocket协议录制的脚本里进行参数化
     
    操作步骤:因为winsocket 协议录制的脚本

    输入的数据都被录入到data.ws里的,所以我是
    data.ws里进行的参数化.右键选择要参数化的数据->选择"replace
    with parameter"->输入列名->"parameter properties"进行了一些相
     
    关设置: ⑴在生成的文档里输入参数化数据⑵.select next row:unique ⑶.update value on:every iteration ->保存脚本.
     
     
    更多信息,请参看《LR 227个问题.CHM》
    问题很多呢

TAG:

 

评分:0

我来说两句

Open Toolbar