socket通讯,有两种方式,一种是建立长连接(TCP),建立后,不停的发送,接收。另外一种是建立短连接(UDP),建立连接,发送报文,接收响应,关闭连接。两种方式 server的开销不同。

今天出现问题:不管是创建TCP还是UDP连接,发送数据后,接收到数据的长度均为空值。

我的代码如下:

wireshark抓包查看到的结果(有接收到服务发送过来的数据):

运行时查看Loadrunner中打印日志:

多次修改代码后,最后修改接收的buffer 的长度,终于接收到数据

总结:之前看过一篇文章,如果接收到的数据长度不固定,可以指定buffer的数据长度为“*”。 现在才明白,原来 “*” 表示不接收数据 。花费一天的时间,终于搞定。

对于recvbuffer数据长度不一致的问题,或许可以参考http://blog.sina.com.cn/s/blog_6bdd0e1d0101b13r.html 这篇文章。copy 内容如下:

使用LoadRunner录制socket协议的脚本,会发现每个请求都会发送和接受一定长度的数据流,即send buffer和recv buffer;这两个buffer后面都会有个数字,这个数字表示buffer的长度,是一个固定的值。当做性能测试时,执行每次请求响应的数据很多时候是不定长的,如果recv buffer的长度与响应的数据长度不一致,脚本会报错,有两种方法可以解决这个问题:

1、造数据,使响应的数据长度在每次不同请求中都一样。但实际上,方法1是有局限性的,也就是说有些请求通过造数据也不能使响应的数据长度一致,那么我们可以采用方法2。

2、自定义函数,动态解析并接受不定长响应数据流。

以下详细介绍下方法2,以举例讲解的方式来介绍:

【业务场景】:用户进行登录操作,每次登录的响应数据由于被加密压缩后才返回的缘故,导致长度不一致。

【协议简介】:用户登录操作采取的协议是自定义协议,协议头中第5,6个byte保存的是整个响应流的长度。

【自定义函数的思路】:先接受响应数据中的前6个bytes,然后取5,6位上的字节转换成int类型,得到整个响应流的长度,从而计算出剩下未被接受的数据长度,再接受剩下的数据。

【代码实现】:

第一部分,录制后未经修改的脚本如下:

  1. Action()
  2.  
  3. {
  4.  
  5. lr_start_transaction("login");
  6. lrs_create_socket("socket6","TCP","RemoteHost=172.16.4.16:1122", LrsLastArg);
  7.  
  8. //登录请求
  9. lrs_send("socket6", "buf1",LrsLastArg);
  10.  
  11. lrs_receive("socket6","buf2",LrsLastArg);
  12. lrs_close_socket("socket6");
  13.  
  14. lr_end_transaction("login",LR_AUTO);
  15. return 0;
  16. }
  17.  
  18. send buf1 49
  19.  
  20. "\x00\x00"
  21.  
  22. recv buf2 291 //每次请求的响应数据长度不一定是291个字节
 
【上述脚本的问题】:
 
recv buf2 291 后面的这个数字表示收到的buffer长度,这个长度在这里就固定死了,也就说每次执行这个脚本的时候都会按这个长度来接受解析响应数据,如果实际的响应数据长度与这个长度不一致会报以下错误:
 
Action.c(xx): Mismatch in buffer's length (expected 291 bytes, 295 bytes actually received, difference in 4 bytes)
 
 
第二部分,自定义函数和录制后修改的脚本如下:
 
为了能够动态接收响应数据,我们自定义了一个接收函数,如下:
 
  1. #include "lrs.h"
  2. int custom_lrs_receive(char *sock_desc, char *buf_desc,void *dummy)
  3. {
  4. int rc;
  5. int buf_len = 6;
  6. char szBytesLength[30], *buf = NULL, *pszError, *pszLastChar;
  7.  
  8. rc = lrs_receive_ex(sock_desc, buf_desc, "NumberOfBytesToRecv=6", LrsLastArg);
  9.  
  10. if (rc != 0) //正常情况下函数返回为0,非0表示函数有错误
  11. {
  12. lr_error_message("Receive 6 bytes failed. The error code = %d", rc);
  13. return -1;
  14. }
  15.  
  16. //判断前6个字节是否接受成功
  17. lrs_get_last_received_buffer(sock_desc, &buf, &buf_len);
  18.  
  19. if (buf == NULL || buf_len != 6)
  20. {
  21. lr_error_message("receive of %s failed", buf_desc);
  22.  
  23. return -1;
  24. }
  25.  
  26. sprintf (szBytesLength, "NumberOfBytesToRecv=%d", fiFromHexBinToInt(buf) - 6);
  27. //调用另一个自定义函数:计算总长度的函数
  28.  
  29. lr_debug_message(LR_MSG_CLASS_FULL_TRACE, "!!!! Bytes length = %s", szBytesLength);
  30.  
  31. rc = lrs_receive_ex(sock_desc, buf_desc, szBytesLength, LrsLastArg);
  32.  
  33. if (rc != 0)
  34. return -1;
  35.  
  36. return 0;
  37. }
  38.  
  39. int fiFromHexBinToInt(char *szBuffer)
  40. {
  41. int i, j, iIntValue = 0, iExp = 1;
  42.  
  43. //一个字节一个字节的取值,循环2次,分别取第6位,第5位上的字节
  44. for( i = 1; i >= 0; i--)
  45. {
  46. iExp = 1;
  47. //从16进制字节流转换成int类型:2个byte4个bit,每个字节的低位分别需要乘以16的0次方和16的2次方;
  48. for (j = 2; j > i*2; j--)
  49. iExp *= 16;
  50.  
  51. iIntValue += (szBuffer[i+4] & 0x0000000f) * iExp + ((szBuffer[i+4] & 0x000000f0) >> 4) * iExp * 16;
  52. }
  53. lr_output_message("the length is %d", iIntValue);
  54.  
  55. return iIntValue;
  56. }
  57.  
  58. Action()
  59. {
  60. lr_start_transaction("login");
  61.  
  62. lrs_create_socket("socket6", "TCP", "RemoteHost=172.16.4.16:1122", LrsLastArg);
  63.  
  64. // 登录请求
  65. lr_think_time(5);
  66. lrs_send("socket6", "buf1", LrsLastArg);
  67.  
  68. custom_lrs_receive("socket6", "buf2", LrsLastArg); //自定义函数接受不定长数据流

Loadrunner 中socket协议RecvBuffer接收到数据长度为空的更多相关文章

  1. Loadrunner中socket协议中的三个关联函数

    这3个函数其实都可以动态获取运行中收到的数据包中的数据,只要跟在要获取的收取数据包脚本后面即可.其中:lrs_save_searched_string和lrs_save_param如果buf_desc ...

  2. 自行控制loadrunner的socket协议性能测试 (转)

    一前言 二任务的提出 三实现方案讨论 四技术要点讲解 如何开始录制一个最简单的收发数据包脚本 写日志文件 一行一行读数据包文件 字符串转换为十六进制数据包 发送自己定义的数据包 接收数据包到自定义缓冲 ...

  3. LoadRunner中winsocket协议学习

    首先让我们先看一下loadrunner- winsock 函数 一览表:        lrs_accept_connection 接受侦听套接字连接 lrs_close_socket 关闭打开的套接 ...

  4. LoadRunner编写Socket协议脚本方法

    本文主要介绍使用LoadRunner手工编写Windows Socket协议测试脚本的方法. 通过LoadRunner编写Windows Socket协议测试脚本,总体说来,比较简单.就像把大象放进冰 ...

  5. loadrunner使用socket协议来实现客户端对服务器产生压力实例。(通过发送心跳包,达到连接多个客户端的目的)

    #include "lrs.h" vuser_init(){ char *ip; int handler; //编写获取LR分配的Vuser IP函数,将IP保存在ip变量中. i ...

  6. AJAX中使用post,get接收发送数据的区别

    如何发起请求 xhr.send(); 备注: 如果是get方式,send()命令中不用写任何参数 传递的数据可以写在url中,服务器用$_GEET["参数名"]接收 如果是post ...

  7. loadrunner socket协议问题归纳(3)

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

  8. loadrunner socket协议问题归纳(0)

    一.概述         Loadrunner拥有极为丰富的工具箱,供予我们制造出各种奇妙魔法的能力.其中就有此次要讨论的socket套接字操作.     二.socket概述         soc ...

  9. 品味性能之道<九>:利用Loadrunner编写socket性能测试脚本简述

            一.概述         Loadrunner拥有极为丰富的工具箱,供予我们制造出各种奇妙魔法的能力.其中就有此次要讨论的socket套接字操作.     二.socket概述     ...

随机推荐

  1. JavaScript Function.call() 函数详解

    语法 functionObject.call( [ thisObj [, arg1 [, arg2 [, args...]]]] ) call()函数用于调用当前函数functionObject,并可 ...

  2. HTML学习笔记 w3sCss盒子模型应用案例(div布局) 第十一节 (原创) 参考使用表

    * { margin: 0px; padding: 0px; } .top { width: 100%; height: 50px; background-color: antiquewhite; } ...

  3. 【Kafka源码】ReplicaManager启动过程

    在KafkaServer启动过程的入口中,会启动Replica Manager,众所周知,这是一个副本管理器.replica在Kafka中扮演的角色很重要,是保证消息不丢失的一个重要概念. repli ...

  4. Adobe Audio 分轨录音教程(需要KX,Live机架)

    一.需要的硬件和软件 1. 创新5.1声卡或7.1声卡: 2. 已安装KX驱动和Live机架,经过测试安装后需要重启电脑才能生效. 3. 已安装Adobe Audition 3.0 二.测试环境 WI ...

  5. 阿里云ecs初始化磁盘后远程连接不到服务器

    阿里云初始化磁盘后远程连接不到服务器 报错: WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! ... 原因:阿里云ecs第一次链接服务器之后会在本地电 ...

  6. 结合GET(),POST()实现一个简单、完整的服务器

    复习一下: 基础模块 作用 fs fs模块用于对系统文件及目录进行读写操作 http 创建服务器.e.g.http.createServer(); queryString 把url带的参数串转化为数组 ...

  7. Oracle 存储过程的导出导入序列的导出

    昨天发布网站,需要将oracle的存储过程导出来,再在新的电脑加上去.登陆—>工具—>导出用户对象—>选取需要导出的存储过程—>导出 保存格式为.sql.当然利用该种方法也可以 ...

  8. Redis全面介绍

    最近重新认识了一下Redis,借着这个机会,也整理一篇算是比较详尽和全面的文章吧.   缓存 缓存就是数据交换的缓冲区(称作Cache)——摘自百度百科.无论是在计算机硬件体系结构还是软件体系结构中, ...

  9. bootstrap导航栏.nav与.navbar区别

    刚刚看了bootstrap的导航栏,发现有点弄混了,现在来整理一下: 一.简单的ul,li组成的导航: <ul class="nav nav-pills justify-content ...

  10. JVM菜鸟进阶高手之路十四:分析篇

    转载请注明原创出处,谢谢! 题目回顾 JVM菜鸟进阶高手之路十三,问题现象就是相同的代码,jvm参数不一样,表现的现象不一样. private static final int _1MB = 1024 ...