发布新日志

  • 脚本:http接口调用2-post方式 ,form表单

    2017-04-19 10:08:20

    http方式的post请求,表单域以键值对的参数形式链接到接口URL,文件域以Form文件表单项的形式进行提交,实例代码:
    Action()
    {
     web_reg_save_param("response",
            "LB=",
            "RB=",
            "Search=Body",
            LAST);
    lr_start_transaction("face_Image");
        web_submit_data("OCRImage","Action=http://10.2.34.22:8080/rvsp-facen/client/compareImage",
        "Method=POST",
        "ENCTYPE=Multipart/form-data",
         ITEMDATA,
         "name=device","value=001",ENDITEM,        /*流水号*/
          "name=clientImage1","value={imagepath1}","File=Yes",ENDITEM,/*图片1*/
          "name=clientImage2","value={imagepath2}","File=Yes",ENDITEM,/*图片2*/
         LAST);
     lr_end_transaction("face_Image", LR_AUTO);
     lr_convert_string_encoding(lr_eval_string ("{response}"),LR_ENC_UTF8 ,LR_ENC_SYSTEM_LOCALE, "response_ok");
    lr_output_message("RESPONSE = %s",lr_eval_string("{response_ok}"));
     return 0;
    }
  • 脚本:http接口调用

    2017-04-19 10:06:16

    关于:对外提供的HTTP接口,http方式的post请求,json方式提交,实例代码编写:
    Action()
    {
     web_reg_save_param("response",
            "LB=",
            "RB=",
            "Search=Body",
            LAST);
    lr_start_transaction("FeatureComp");
     web_custom_request("web_custom_request",
        //"URL=http://10.2.34.70:6000/face/faceCompare.do",
        "URL=http://10.2.34.22:8080/rvsp-facen/faceRepo/icompareByIdTypeNo",
                    "Body={\"base64Img\":\"{NewParam}\",\"idType\":\"1\",\"idNo\":\"430381198101143025\",\"runningNo\":\"11\"}",
        "Method=POST",
        "Resource=0",
        "RecContentType=application/json",
        "Referer=",
        "Mode=HTML",
        "EncType=application/json",
        LAST);
      lr_end_transaction("FeatureComp", LR_AUTO);
     lr_convert_string_encoding(lr_eval_string ("{response}"),LR_ENC_UTF8 ,LR_ENC_SYSTEM_LOCALE, "response_ok");
      lr_output_message("RESPONSE = %s",lr_eval_string("{response_ok}"));
     return 0;
    }
  • LoadRunner调用Java程序—性能测试

    2015-05-22 11:45:27

  • 性能工具使用:资源监控工具Spotlight-使用说明

    2015-05-22 11:38:10

    几年前使用过此工具,发现用于监控远程服务器,非常方面而且快捷。当前再次用于配合压力测试进行资源监控,突然想起来了,以免生疏,在此记录!

     

      1、被监控服务器为Ubuntu server,先在服务器上创建一个用户,专门用于监控使用!

      因为远程监控服务器,需要获取服务器的资源,所以必须要有权限。使用文档明确说明,不能使用root用户,但是我用其他已存在的用户也不行,所以只能创建一个新用户,方便起见就用spotlight作为用户名,设置如下

      >> useradd spotlight

      >> passwd spotlight

      设置完密码就ok了。不错此处,有相关介绍说,要这个用户必须要有root权限才行,但这里我只是创建一个朋友同用户就能。如果创业具有root用户的权限,命令如下,同时建议密码稍微复杂一些

      >> useradd -g root -G root spotlight

      >> passwd spotlight

      设置完密码即可。

     

      2、需要在服务器有监控工具,如sysstat,ubuntu下直接安装即可

      >> apt-get install sysstat

      完成即可

     

      3、本地机器安装spotlight,创建监控信息如下

      进入Spotlight界面,进入File菜单点击Connect,进入如下界面,

      

      双击Add New connection,进入创建一个新的监控链接如下

      

      填充OK即可。

     

      4、监控信息如下:    

      

      监控信息一目了然。

     

      当然Spotlight还可以监控很多很资源,相关如下

      

      

      Spotlight是一款非常轻量级的远程监控工具,当前我们只是用来简单的监控linux服务器。

     

  • 转:内存泄露分析1

    2015-05-22 11:35:51

    性能测试之内存泄漏

      关于内存泄漏,相信大家都不陌生,压力测试中经常会出现,本人最近在做一个压力测试中就着实体会了一下,上来分享分享。

      内存泄露是指程序中间动态分配了内存,但是在程序结束时没有释放这部分内存,从而造成那一部分内存不可用的情况,重起计算机可以解决,但是也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是由软件设计缺陷引起的。

    以发生的方式来分类,内存泄漏可以分为4类:
    1. 常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。
    2. 偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
    3. 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。
    4. 隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。
      本人最近就在对一个Http应用进行压力测试,发现被测试的对象进程在并发100时内存占用达到20%,当压力到达1000的时候,内存就持续上升,达到60%,最后压力结束后,内存仍旧停留在60%的使用率,然后重启了系统发现内存已经恢复了正常,于是在第二轮测试时再次不断加压,同时关注性能计数器中的如下指标

    Memory\ Available Bytes 是指剩余的可用物理内存,单位是兆字节(参考值:>=10%)。表明进程当前可使用的内存字节数。

    Memory\ Pages/sec 是表明由于硬件页面错误而从磁盘取出的页面数,或由于页面错误而写入磁盘以释放工作集空间的页面数。

    Process\Private Bytes 是指当前进程中运行的私有内存,如果此内存不断攀升,表示当前存在的内存泄漏,一般情况如果资源合理利用的话,该指标值波动比较平稳。

    通过有效的监控以上计数器可以方便我们判断内存泄漏问题,同时需要开发人员配合进行内存查找,定位分析哪些程序存在内存泄漏。最后通过开发人员的调试,问题很快定位了,确实有程序没有释放内存,最后再次施压的结果是内存持续在一个值上下波动,一般参考值在20%左右,不过这个根据具体的内存空间来定,当然如果可以更小最好了,表明内存合理利用和分配。当然了,检测内存泄漏的方式很多,LoadRunner施压是可以结合响应时间的曲线图来监控也可。

      从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积,而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄漏它更难被检测到。对于开发人员来说,熟悉java、C++等应该都了解,通常我们定义一些变量,或者实例化一些对象,比较常用就是new方法,然后通过delete方法进行销毁,如果定义的东西比较多了,也就是想一天申请的内存空间就多了,如果一旦没有合理的管理和消化,就会忘记最后做一些内存回收的处理,导致一些变量和实例对象没有处理掉,最后在程序运行一段时间之后就发现我们的内存不断在攀升,长时间下来积累了就占用了大量的内存空间,导致其他进程无法获取到内存资源,无法去处理其他应用,最后服务就shut down,等等之类情况都比较多见,不过这些也基本取决于开发人员的经验所致,在程序编写过程中合理的使用和管理内存是非常重要的,因为此类问题一般只有在性能测试中体现出来,功能测试是完全没有表现的迹象。

      其实,内存泄漏问题多半在压力测试中出现也是源于程序编写过程中没有规范化管理所导致,开发人员需要结合内存监测工具来有效监控自己的程序,这样才会避免这些个低级的瓶颈出现,所以说性能测试只是为程序提供优化建议,而不应该成为帮助开发人员调试程序的一种手段。

  • LR工具使用问题集锦

    2015-02-28 16:25:24

    1、LRcontroller中 ,想做一个集合点,我已经在脚本了加入了lr_rendezvous函数 为何controller中的rendezvous还是显示灰色不可使用?
    1)场景的设置选择的方式不对,如果选择的是 面向目标 的场景方法,集合点是不可用的 。新建场景的时候“Manual Scenario”下的check box不能选中,取消选中就好。
    2)另外一种是,没有虚拟用户数,也会是灰色的。
  • LR工具使用问题集锦

    2015-02-28 16:25:24

    1、LRcontroller中 ,想做一个集合点,我已经在脚本了加入了lr_rendezvous函数 为何controller中的rendezvous还是显示灰色不可使用?
    1)场景的设置选择的方式不对,如果选择的是 面向目标 的场景方法,集合点是不可用的 。新建场景的时候“Manual Scenario”下的check box不能选中,取消选中就好。
    2)另外一种是,没有虚拟用户数,也会是灰色的。
  • 日志

    2015-01-23 11:33:07

    LR日志输出  

    2013-01-16 23:21:40|  分类: 测试 |  标签: |举报 |字号 订阅

    转:http://blog.csdn.net/oeardi/article/details/5680557

    http://blog.csdn.net/oeardi/article/details/5715516

    在Windows环境下,日志文件output.txt保存在脚本目录中;在UNIX环境下,保存在标准输出中。

     

    【Vuser】——【Run Time Settings】——【General】——【Log】

     

    1、【Enable logging】启动日志功能;(建议运行场景进行负载测试时关闭此项)

    2、【Send messages only when an error occurs】仅发送出错时的日志,可设置缓存大小(默认1KB);

    3、【Always send message】发送所有日志;

    4、【Standard log】标准日志,脚本运行时发送函数信息;

    【Extended log】扩展日志:

    5、【Parameter substitution】脚本运行时,在【Replay log】显示参数信息、参数值;

    6、【Data returned by server】记录服务器返回的所有数据;

    7、【Advanced trace】多用于脚本调试,记录VU在运行期间发送的所有函数信息。

    ========================================

    【Replay log】显示的日志颜色:

    1、红色:错误信息;

    2、橙色:迭代信息;

    3、蓝色:事件信息;

    4、黑色:输出信息;

    5、绿色:字符信息。

    ========================================

    输出函数:

    1、lr_log_message()    // 输出信息,并记录到 output.txt 中

    2、lr_output_message()    // 输出信息,不记录到日志文件中

    3、lr_message()    // 输出信息,不记录到日志文件中

    4、lr_error_message()    // 输出信息,不记录到日志文件中

  • 关于EXTRARES的扩展说明—性能测试进阶指南 LoadRunner 11实战(第二版)

    2015-01-07 13:50:40

  • 谈谈LoadRunner中lr_load_dll函数的应用[转]

    2015-01-07 13:42:39

      

    2012-03-07 17:31:17|  分类: LoadRunner |  标签: |举报 |字号 订阅

    在用LoadRunner进行压力测试的过程中,我们常常会遇到这样的情况:被测对象软件的客户端操作界面使用浏览器或可执行程序界面,后台则调用通用或私有的动态链接库(*.dll)同服务器进行通讯和数据传输。这时候如果通过VuGen不能成功录制脚本的话,可以考虑LoadRunner中的一个特殊的函数lr_load_dll。
        下面我们以某收费系统测试为实例介绍一下该函数的应用:
        某收费系统采用“收费点—收费站—数据中心”的三层结构,通过开发方提供的专用动态链接库将生产数据由收费点上传至收费站和数据中心,收费点用户操作界面则是由开发方根据该高速公路管理部门的要求专门定制的应用程序,收费点用户操作界面调用动态链接库中的函数进行数据传输。由于动态链接库在数据传输时进行了处理,使用Winsock协议录制测试脚本则可能使调试工作复杂化。考虑到开发方能够提供明确的动态链接库函数说明,我们设计用lr_load_dll直接调用动态链接库的方式制作脚本。
        函数说明:
    动态链接库文件名称:CPGS_MID.dll
    函数名:Mid_Data_Transession
    实现目标:收费点上传传原始记录结算中心或收费站传原始记录
    调用函数:
    Mid_SetTarget  //设置目标节点
    Mid_UploadData //上载数据
    调用示例:
    Mid_Data_Transession ()
    {
    long reqid;  //变量定义
    char form[32];
    int iRet;
    char aBuf[1024]; //数据字串
    //输入参数赋值
    Mid_SetTarget(&02000,"IN_CENTER"); //设置数据传输目标及目标类型
    strcpy( aBuf, “上传记录对象” );  //设置上传记录对象
    iRet = Mid_UploadData (form,aBuf,reqid); //数据上载至
    if( iRet == -1000)       //判断上传结果
    {
       printf(“交易提交失败”);    //上传失败,反馈出错信息,并记录日志
       return -1;
      }
      return 0;
     }
    测试脚本中调用方式如下:


    谈谈LoadRunner中lr_load_dll函数的应用[转] - the_show_27@yeah - Autumn is fallen!

     


        这样就实现了在LoadRunner中调用动态链接库,之后进行并发场景设置等工作与正常压力测试方式一致。此外还需要注意的是,在调用一个动态链接库函数之前,需要LoadRunner能识别该动态链接库文件,即该文件是在系统缺省或声明路径下,能够被正常引用。
        总结:我们知道LoadRunner提供了功能强大的API集合,可以满足大多数性能测试的需求。但在某些特定情况下,这些API仍然有覆盖不到的地方,这就导致LoadRunner可能不便或者无法捕捉相应的数据信息。对这种情况,通过直接调用动态链接库函数向服务器加压可以简化测试脚本的制作过程,提高测试工作的效率,不失为一种理想的解决方案

  • LR:socket

    2015-01-03 18:58:59

        

    自行控制loadrunner的socket协议性能测试

    分类: 【性能测试】 188人阅读 评论(0) 收藏 举报
    [-]
    1. 一前言
    2. 二任务的提出
    3. 三实现方案讨论
    4. 四技术要点讲解
      1. 如何开始录制一个最简单的收发数据包脚本
      2. 写日志文件
      3. 一行一行读数据包文件
      4. 字符串转换为十六进制数据包
      5. 发送自己定义的数据包
      6. 接收数据包到自定义缓冲区
      7. 从自定义缓冲区读出数据
      8. 如何释放自定义缓冲区
      9. 如何根据数据包返回计算为十进制数
    5. 五小节

     

     

    摘要:通过实例讲解loadrunner中的socket协议性能测试的一种测试方法,如何不依赖loadrunner既定规则,自行控制收发数据包

    关键词:Loadrunnersocket,自行控制,收发数据包

     

    一.前言

     

    用过loadrunnersocket协议进行性能测试的同学都知道,只需要录制短短的几句命令,就可以实现socket的链接、收发数据包和关闭链接,一时大爽,不过紧跟着的就是没完没了的折磨。刚开始参数化数据包发送接收都行,慢慢的发现,很多情况下,收发数据包的长度和内容都是不可确定的,加上十六进制和ASCII,甚至协议和加密等等因素混合在一起,简直就是灾难。于是自行控制数据包收发成了可选项,虽然loadrunner提供了相关的函数,但是真的面对进制转换,面对没完没了的<memory violation : Exception ACCESS_VIOLATION received>,很多人只能另外寻找办法完成任务。

     

    本来想全面剖析loadrunnersocket协议性能测试,发现需要厘清的细节太多了,只能尽力讲清楚下面这个例子中遇到的各个知识点了。

     

     

     

    二.任务的提出

     

    这个性能测试是很常见的一种情况,前置机链接了各类不同的硬件设备客户端,各个硬件设备客户端使用了不同的协议,协议承载了大量的不同业务,不过数据包的基本结构相同,由首部、包体和校验码组成,既有TCP链接也有UDP链接,数据发送方式上都是使用的短链接,也就是链接上服务器,发送完数据就立刻关闭了链接。现在需要loadrunner模拟不同的硬件设备,测试前置机的并发能力。

     

     

    数据包结构:

     006.jpg

     

    系统架构:

    001.jpg

     

     

    三.实现方案讨论

     

    这个场景很常见,不过也比较复杂。

     

    如果采用传统的录制回放,需要先选择几种有代表性的硬件类型和重点业务,录制出脚本,可以想象需要录制的脚本有很多,如果进行参数化,必须要搞清楚各种协议,重新组包,这个工作量太大了。

     

     

    或者开发提供两个动态链接库,一个用来对各种协议实现编解码,另外一个包括了需要模拟的硬件类型的重点业务,第二个动态链接库调用第一个,在loadrunner中加载了动态链接库以后,直接调用相关的业务操作函数就可以了。这个够通用,不过开发谁有空搭理你呀。况且如果说这个,这篇文章就不用写了。

     

     

    那还有第三种方法,现在收发的数据包在前置机上有日志文件保存,可以将各种硬件类型发送的数据包日志文件分类搜集到,然后做两个脚本,一个TCP的,一个UDP的,逻辑都是同样的,打开数据表日志文件,读出数据包发送,将发送和接收到的数据包写入本地日志文件,这样就只需要编写两个脚本,拷贝出多份,每个脚本下放入不同的数据包文件模拟出不同的硬件类型。

     

    看起来这种方式最简单,再分析一下,是否可行。

     

    很多协议中会在链接上服务器后,服务器端提供一个唯一串返回,做为一次通讯的唯一标识,加入到后续的数据包中,这里协议倒是没有这个问题,要不每次发送数据包前,还得根据返回的唯一串来修改要发送的数据包,真是幸运。

     

    这样看来建立链接后,数据包可以不做任何修改就能发送出去。不过有些业务,例如增加业务,前置机接收到任务后,可能会写入表,如果已经存在可能会冲突,所以测试前需要清空数据库,只保留初始化数据。

     

    这样还有一个好处,测试的业务和实际生产的业务是完全一致的,无论种类还是比例。缺点是这里的数据包文件会不会不够大,发一会就发完了,看来还需要有个工具来生成足够多的数据包的文件。不过怎么说也是松散耦合了。

     

    经过确认,也没有出现某硬件的某个业务,混合使用TCPUDP的情况。

     

    看来这个方案没有太大的问题,就这样吧。

     

     

     

     

    四.技术要点讲解

     

    1. 如何开始录制一个最简单的收发数据包脚本

     

    开始录制脚本的时候,使用了一个绿色软件SocketTool.exe,在本机启动了一个TCP服务器端:

    002.jpg

     

     

    使用loadrunner录制windows application,启动一个新的SocketTool.exe,创建一个TCP Client,链接刚才启动的服务器,钩选上显示十六进制值,发送313233,别写空格进去,点击发送数据,然后再在服务器端发送点数据回客户端,最后客户端点击断开,脚本就录制完成了。

    003.jpg

     

    004.jpg

     

    脚本就四句:

    lrs_create_socket("socket0", "TCP", "LocalHost=0", "RemoteHost=server:60000", LrsLastArg);

    lrs_send("socket0", "buf0", LrsLastArg);

    lrs_receive("socket0", "buf1", LrsLastArg);

    lrs_close_socket("socket0");

     

    数据文件data.ws:

    ;WSRData 2 1

     

    send  buf0 3

             "123"

     

    recv  buf1 3

             "456"

     

    -1

     

    后面的脚本就在此基础上修改了。

     

     

     

    2. 写日志文件

     

    假设脚本并发了五个用户,如果都往一个日志文件里面写入内容,就可能出现各个用户日志交织在一起的情况,如果需要每个用户独立使用自己的日志文件,可以创建一个参数vurid

     

    005.jpg

     

    sprintf(cReqSeqNo,"%s%s20d459b3412a2b",cNow,);

     

     

    定义变量:

    char cLogFile[100]="\0";   //日志文件

    long filedeslog=0;         //日志文件句柄

     

    vuser_init中打开日志文件:

     

    sprintf(cLogFile,"lrsocket%s.log",lr_eval_string("{vurid}"));

    if((filedeslog = fopen(cLogFile, "a+")) == NULL)

    {

             lr_output_message("Open File Failed!");

             return -1;

    }

     

    //写入日志文件内容

    fwrite("\nopen file:", strlen("\nopen file:"), 1, filedeslog);

    fwrite(cFileName, strlen(cFileName), 1, filedeslog);

    fwrite("\n", 1, 1, filedeslog);

     

    vuser_end中关闭日志文件:

    fclose(filedeslog);

     

     

    3. 一行一行读数据包文件

    定义部分:

    char cFileName[100]="\0";  //数据包文件名

    long filedes=0;            //数据包文件句柄

    char cLine[2048]="\0";      //文件中一行

     

    读文件方法:

    sprintf(cFileName,"%s","data.txt");

    if((filedes = fopen(cFileName, "r")) == NULL)

    {

             lr_output_message("Open File Failed!");

             return -1;

    }

    while (!feof(filedes)) {

     

             fscanf(filedes, "%s", cLine);

             lr_output_message("read:%s", cLine);

    }

     

    fclose(filedes);

     

     

     

    4. 字符串转换为十六进制数据包

     

    定义:

    unsigned char cOut[1024]="\0";      //记录转换出来的数据包,发送出去的数据包

     

    在这里虽然表面是字符数组,不过请大家千万别把cOut[]当成字符串来处理,而应该理解为一个存放一系列十六进制数据的数组。这有什么区别吗?当然有。

     

    比如你现在要发出一个数据包16进制是:31 32 00 33 34,该数组中就该存储着(十进制)

    cOut[0]=49

    cOut[1]=50

    cOut[2]= 0

    cOut[3]=51

    cOut[4]=52

    发送数据包的时候就应该发送长度为5,如果处理为了字符串,发送strlen(cOut),可以想象,逢零就停止了,只发出去了前两个字节。接收的时候自然也不可以使用strcpy(cOut,BufVal),因为遇到零就会停止,如果包中有00字节,就会造成数据不完整。

     

     

    //进制转换

    m=0;

    memset(cOut,0,sizeof(cOut));

    for (k=0;k<strlen(cLine);k++) {

             if (k % 2==1) {

                       cTmp[0]=cLine[k-1];

                      cTmp[1]=cLine[k];

                       cTmp[2]=0;

                       sscanf(cTmp,"%x", &lngTrans);

                       cOut[m]=lngTrans;

                       m++;

             }

    }

     

    首先初始化cOut的所有字节为0;

    读取从文件中取出的一行;

    每遇到偶数字符,就读出来两个字符,放入cTmp字符串,使用sscanf(cTmp,"%x", &lngTrans);

    比如cTmp中存着”31”,理解为16进制转换出来,lngTrans=0x31;

    然后再把转换出来的数据放入cOut中,得到要发出的数据包

     

    如果想看看cOut里面存的内容:

    unsigned char *p;

     

    p=cOut;

    for (i=0;i<strlen(cLine)/2;i++) {

             lr_output_message("package ready:%x,%d,%x",p,*p,*p);

             p++;

    }

    loadrunner中不可以直接引用cOut[0]的方式打印值,需要使用指针。连指针的地址都打给你看了,这下够清楚了吧。

     

     

    5. 发送自己定义的数据包

     

    建立链接我就不写了,发送自己定义的数据包:

    lrs_set_send_buffer("socket0", (char *)cOut, strlen(cLine)/2 );

    lrs_send("socket0", "buf0", LrsLastArg);

     

    说明:

    1.         (char *)cOut 是因为函数的参数定义
    int lrs_set_send_buffer ( char *s_desc,char *buffer, int size );

    2.         strlen(cLine)/2不可写为strlen(cOut),一定要牢牢记住这里不是发送的字符串,而是一个二进制数据包;

     

     

     

    6. 接收数据包到自定义缓冲区

    代码:

    char *BufVal;              //记录接收到的数据包

    int intGetLen=0;           //记录接收数据包的长度

     

    lrs_receive_ex("socket0", "buf1", "NumberOfBytesToRecv=4", LrsLastArg);

    lrs_get_last_received_buffer("socket0",&BufVal, &intGetLen);

     

    说明:

    1.         intGetLen必须定义为int,而不可是long,为啥?函数定义决定的:
    int lrs_get_last_received_buffer ( char *s_desc, char **data,int *size );

    2.         "NumberOfBytesToRecv=4"此处loadrunner的帮助中例子写错了,当时我照着粘贴下来,死活报那个恐怖的<memory violation : Exception ACCESS_VIOLATION received>,后来仔细看了看,明白了,例子上NumberOfBytesToRecv前面多了一个空格,删除了就可以了;

    3.         定义接收数据包长度,这个参数只适应于TCP协议,UDP就不行了

     

     

    7. 从自定义缓冲区读出数据

     

    代码:

    char cGetLen[5]="\0";      //记录接收到的前四个字节

     

    memset(cGetLen,0,sizeof(cGetLen));

    for (j=0;j<intGetLen;j++) {

             sprintf(cT1,"%02x",(unsigned char)*BufVal);

             strcat(cGetLen,cT1);

             BufVal++;

    }       

     

     

    说明:

    1.         初始化接收数组cGetLen所有字节为0

    2.         (unsigned char)*BufValBufVal指向的值一个个字节读出,按照无符号数解读为16进制和十进制,如果不设定为无符号数,碰到诸如0xA0,转换成十进制字符串就不是”160”,会变成一个负值”-95”,高位被解读为了符号;

    3.         cGetLen不用定义为无符号的,他只是用来将16进制串转化为字符串写入日志用的,并不是存储的数据包

     

     

    8. 如何释放自定义缓冲区

     

    代码:

    for (j=0;j<intGetLen;j++) {

             BufVal--;

    }

    lrs_free_buffer(BufVal);

     

    用完了缓冲区BufVal后需要释放,否则BufVal不断的取得返回,就会越来越长,定位就变得麻烦,用起来不方便。最初释放的时候也是遭遇<memory violation : Exception ACCESS_VIOLATION received>。查看了例子,想了半天,终于明白了,我之前读取缓冲区操作了指针,而释放需要是初始的头指针,于是写了一段狗血的代码,通过循环,回到初始状态进行释放。-_-|||

     

     

     

     

    9. 如何根据数据包返回计算为十进制数

     

    接收数据的时候是分成两个步骤,首先取得四个字节,计算出后续数据包的长度,然后再指定长度进行接收。所以得到返回的四个字节后,需要计算出长度。这里我是一个字节一个字节转换为十进制的值,例如:

    0x11 0x22 0x33 0x44=0d17 0d34 0d51 0d68=256^3*17+256^2*34+256^1*51+256^0*68

     

    代码:

    定义:

    unsigned char cT2[3]="\0"; //记录接收到的10进制字符串

    long lngGetData=0;         //记录后续数据包长度

    int iByte=0;               //四个字节的单个字节的10进制数

    int iaR[4]={0,0,0,0};      //记录四个字节的十进制值

     

     

    for (j=0;j<intGetLen;j++) {

             sprintf(cT2,"%d",(unsigned char)*BufVal);

             iByte=atoi(cT2);

             iaR[j]=iByte;

             BufVal++;

    }

     

    lngGetData=iaR[0]*16777216+iaR[1]*65536+iaR[2]*256+iaR[3];

     

     

    通过atoiASCII码转换为int值,比如cT2=”160”atoi后就成了数值的160

     

     

     

    五.小节

     

    学多用少是一个大的战略原则,尽可能用最简单最适合的法子解决问题,loadrunnersocket测试本篇中没有提到如何和参数打交道的问题,也没有描述UDPTCP的细节差异,接收报文也只是长度数据两段式的收取,没有讲到不确定长度使用终止串的收取方法,一篇文章终归难以尽言,抛砖引玉,如有错漏,不吝赐教。

     

     

    代码和工具下载:

    http://download.csdn.net/detail/testingba/4305645


    转自:http://blog.csdn.net/testingba/article/details/7571911

  • LR:IP欺骗设置

    2015-01-03 17:10:41

    应用程序服务器和网络设备使用IP地址来识别客户端。应用程序服务器通常会对来自同一计算机的客户端信息进行高速缓存。网络路由器尝试对原信息和目标信息进行高速缓存

    以优化吞吐量。如果多个用户具有相同的IP地址,服务器和路由器都会尝试优化。由于同一Load Generator上的Vuser具有相同的IP地址,因此服务器和路由器优化不能反映真

    实情况。

    LoadRunner的多个IP地址功能使允许在单个Load Generator上的Vuser可以使用多个IP地址来识别。服务器和路由器将这些Vuser识别为不同的Load Generator,因此,测试更加贴近显示。

    可以使用LoadRunner的IP欺骗功能创建多个IP地址。只需将新IP地址添加到计算机一次,就可将这些地址用于所有场景。

    下面简要介绍在LoadRunner 中使用IP 欺骗的方法:

    1)设置虚拟IP地址

    注意:Load Generator 机器必须使用固定的IP,不能使用动态IP。

    第一步:打开:开始->程序->HPLoadrunner->tools->Ip wizard,如图所示:



    “增加新IP”选择第一项,“使用保存的文件增加IP”选择第二项,“释放已经设置的IP”选择第三项。

    点“下一步”,出现如图所示的界面:



    这里输入服务器的IP 地址,IP 向导将检查服务器的路由表是否需要更新,这里也可以不输

    入,直接点“下一步”,出现如图所示的界面:


    在这里可以使用Remove 按钮删除选定的虚拟IP,点Add 按钮添加IP,如图所示:


    这里根据输入的IP 的第一个值和数量,自动添加到虚拟IP 列表中,例如:192.168.139.41 5,则增加的虚拟IP 是:192.168.139.41、192.168.139.42、192.168.139.43、192.168.139.44、192.168.139.45.点OK 按钮后如图所示:


    点“完成”按钮,如图所示:


    使用Save as…可以将本次增加的IP 保存成.ips 文件,下次再使用时就可以直接选择此文件了。 点“OK”按钮后完成虚拟IP 设置。设置的虚拟IP 都生效了,此时使用ping 命令会发现都能ping 通。确认虚拟IP 是否都生效的方是:在运行中输入cmd,在命令窗口录入ipconfig,然后就能看到已经生效的所有IP。

    2)使用虚拟IP

    在Controller 中,选择 Scenario->Enable IPSpoofer,设置允许使用IP 欺骗。如图所示:


    “查看虚拟IP”是否实现也可以在脚本中使用lr_get_vuser_ip 函数来得到当前虚拟用户

    的IP 地址,在脚本中加入如下语句:

    Action()

    {

    char *ip;

    ip = lr_get_vuser_ip();

    if( ip )

    lr_message("The IP address is %s" , ip);

    else

    lr_message("IP spoofing disabled");

    return 0;

    }

    在controller中,使用vuser—>showvuser log功能,可以查看user的IP地址。当user数超过虚拟IP数时,有的userIP相同。

    3)使用虚拟IP做完测试后,需要释放所有虚拟IP

    打开IP Wizard,释放所有虚拟IP。重新启动计算机,这样虚拟IP 地址就释放了,否则将占

    有路由表中的IP 地址,别人使用这些IP 地址时将发生冲突。

  • LR的日志详解

    2015-01-03 17:08:39

Open Toolbar