【Loadrunner winsocket菜鸟实践四】如何玩转TCP/UDP请求(终结版)

步骤1:新建CRC8.c文件,代码如下:

//CRC8 字节表
const  unsigned char CRC8Table[]= { 
0,94,188,226,97,63,221,131,194,156,126,32,163,253,31,65, 
157,195,33,127,252,162,64,30, 95,1,227,189,62,96,130,220,
35,125,159,193,66,28,254,160,225,191,93,3,128,222,60,98,
190,224,2,92,223,129,99,61,124,34,192,158,29,67,161,255,
70,24,250,164,39,121,155,197,132,218,56,102,229,187,89,7,
219,133,103,57,186,228,6,88,25,71,165,251,120,38,196,154,
101,59,217,135,4,90,184,230,167,249,27,69,198,152,122,36,
248,166,68,26,153,199,37,123,58,100,134,216,91,5,231,185,
140,210,48,110,237,179,81,15,78,16,242,172,47,113,147,205,
17,79,173,243,112,46,204,146,211,141,111,49,178,236,14,80,
175,241,19,77,206,144,114,44,109,51,209,143,12,82,176,238,
50,108,142,208,83,13,239,177,240,174,76,18,145,207,45,115,
202,148,118,40,171,245,23,73,8,86,180,234,105,55,213,139,
87,9,235,181,54,104,138,212,149,203, 41,119,244,170,72,22,
233,183,85,11,136,214,52,106,43,117,151,201,74,20,246,168,
116,42,200,150,21,75,169,247,182,232,10,84,215,137,107,53 
};

//CRC8 校验
 unsigned char Checksum_CRC8(unsigned char *buf,int len)
{	
	unsigned char check = 0;
	while(len--)
	{
		check = CRC8Table[check^(*buf++)];
	}
	free(buf);
	return (check)&0x00ff;	
}

步骤2:创建一个send_buff.c文件:


//将10进制数字转2位的16进制字符串
char buffer_2 [1024];
char * inttohex_2(int aa)
{
    sprintf(buffer_2, "%02lx", aa);
    return (buffer_2);
}

//将10进制数字转4位的16进制字符串
char buffer_4 [1024];
char * inttohex_4(long aa)
{
    sprintf(buffer_4, "%04lx", aa);
    return (buffer_4);
}

//将10进制数字转8位的16进制字符串
char buffer_8 [1024];
char * inttohex_8(long aa)
{
    sprintf(buffer_8, "%08lx", aa);
    return (buffer_8);
}


//将10进制字符串转16进制
char result[1024];
char * toascii_16(char from[],int size)
{ 

	int i,z,k;
	char temp[1024];
	z=0;
	for(i=0;i<size;i++) {
		itoa(from[i], temp, 16);
	    for (k=0;k<strlen(temp);k++) {
		   result[z++]=temp[k];
		}
	}
	return (result);
}

//将10进制字符串转16进制
char resultsn[1024];
char * toascii_sn_16(char from[],int size)
{ 
	int is,zs,ks;
	char temps[1024];
	zs=0;
	for(is=0;is<size;is++) {
		itoa(from[is], temps, 16);
	    for (ks=0;ks<strlen(temps);ks++) {
		   resultsn[zs++]=temps[ks];
		}
	}
	return (resultsn);
}

//将字符串中,某个字符替换成另外一个字符
int ReplaceStr(char* sSrc, char* sMatchStr, char* sReplaceStr)
{
        int StringLen;
        char caNewString[1024];
        char* findPos;
        merc_timer_handle_t timer_ReplaceStr = lr_start_timer();

        lr_debug_message(LR_MSG_CLASS_EXTENDED_LOG ,"Notify:Function 'ReplaceStr' started.");
        findPos =(char *)strstr(sSrc, sMatchStr);
        if( (!findPos) || (!sMatchStr) ){
            lr_debug_message(LR_MSG_CLASS_EXTENDED_LOG ,"Notify:Function 'ReplaceStr' ended with error!");
            return -1;
        }               

        while( findPos)
        {
                memset(caNewString, 0, sizeof(caNewString));
                StringLen = findPos - sSrc;
                strncpy(caNewString, sSrc, StringLen);
                strcat(caNewString, sReplaceStr);
                strcat(caNewString, findPos + strlen(sMatchStr));
                strcpy(sSrc, caNewString);

                findPos =(char *)strstr(sSrc, sMatchStr);
        }
        lr_debug_message(LR_MSG_CLASS_EXTENDED_LOG,"Result:%s",sSrc);
        free(findPos);
        lr_debug_message(LR_MSG_CLASS_EXTENDED_LOG ,"Notify:Function 'ReplaceStr' ended (Duration: %lf)",
                         lr_end_timer(timer_ReplaceStr));
        return 0;
}

//将16进制字符串转为16进制字符数组
int u=0;
unsigned char buf[2048];
unsigned char * Hex_values(char * Buffer,int reset)
{
	int i;
	char * psrc;
	char dst[2048];
	 psrc=Buffer;
     for(i=0;*psrc;i++){
		strcpy(dst,"0X");
		strncat(dst,psrc,2);
		buf[u++]= strtol(dst,NULL,16);
		psrc+=2;
	 }
	 if(reset==2){
		 u=0;
	 }
	return buf;
}


//将所有16进制字符串,转为“\x”格式
int z=0;
int p;
char sernd_buf[2048];
char * send_buffer(char * send_Buffer)
{
	int r;
	char * send_psrc;
	char send_dst[2048];
	 send_psrc=send_Buffer;
     for(r=0;*send_psrc;r++){
		strcpy(send_dst,"\\x");
		strncat(send_dst,send_psrc,2);
		send_psrc+=2;
		for(p=0;p<strlen(send_dst);p++) {
			sernd_buf[z++]=send_dst[p];
		}
	 }
	 z=0;
	return sernd_buf;
}

步骤3:在loadrunner中引入调用代码:

#include "lrs.h"
#include "CRC8.c"
#include "send_buff.c"


char *IMEI_id;
char *ICCID_16;

vuser_init()
{ 	
	int rc;
	lrs_startup(257);

	rc=lrs_create_socket("socket6", "TCP", "RemoteHost=xxx.xxx.xxx.xxx:xxxx", LrsLastArg);
	if (rc==0){ 
       lr_output_message("Socket  was successfully created "); 
	}else{
		lr_output_message("An error occurred while creating the socket, Error Code: %d", rc); 
		 return -1;
	}

	/*--------------------------生成初始化数据---------------------------------- */
	
	 /*--------------生成case公共号------------*/
	 //将10进制字符串转16进制字符串
	 caseID=lr_eval_string("868345031426596");
	 CASE_len=strlen(caseID);
	 lr_output_message("CASE_len>>>:%d",CASE_len);
	 case_id=toascii_sn_16(caseID,CASE_len);
	 lr_output_message("case_id>>>:%s",case_id);

	 /*--------------生成公共序号------------*/
     IC_ID=lr_eval_string("89860zzzzzzzzzzzzzzz");
	 IC_ID_len=strlen(IC_ID);
	 lr_output_message("IC_ID_len>>>:%d",IC_ID_len);
	 IC_ID_16=toascii_16(IC_ID,IC_ID_len);
	 lr_output_message("IC_ID_16>>>:%s",IC_ID_16);
	 
	return 0;
}





#include "lrs.h"

Action()
{		
	char *Data; 
     int NumberOfBytes;
	 char buffer_1[2048]="010b0701c0";
	 char cacr8_values1[1024];
	 unsigned char * Hex_val_1;
	 unsigned char CRC8_1;
	 char * send_buffer_val;

	typedef long time_t;
    time_t t;
	char timec[2048];
	char *tmp;
	int s;

	/*----------------------------------------POST数据-------------------------------------------------*/

	lr_start_transaction("post");
	  //组装版本号
	 strcat(buffer_1,inttohex_2(100));
	 lr_output_message(">>>>>>>>>>>>>>>Buffer01: %s",buffer_1);

	  //组装 case公共号
	 strcat(buffer_1,case_id);
	 lr_output_message(">>>>>>>>>>>>>>>Buffer02: %s",buffer_1);

	  //组装公共序号
	 strcat(buffer_1,IC_ID_16);
	 lr_output_message(">>>>>>>>>>>>>>>Buffer03: %s",buffer_1);
 
	  //组装10个数据包
	 strcat(buffer_1,inttohex_2(10));
	 lr_output_message(">>>>>>>>>>>>>>>Buffer04: %s",buffer_1);

	 for(s=0;s<10;s++){

	/*-----------生成16进制时间戳---------- */

	//生成当前时间的时间戳 //5B 0F F9 16  
     sprintf(timec, "%ld",time(&t));
	  //组装采集时间(单位s)
	 strcat(buffer_1,inttohex_4(atol(timec)));
	 lr_output_message(">>>>>>>>>>>>>>>Buffer05: %s",buffer_1);

	  //组装case1 ms
	  strcat(buffer_1,inttohex_2(120));
	  lr_output_message(">>>>>>>>>>>>>>>Buffer06: %s",buffer_1);

	  //组装case2
	  strcat(buffer_1,inttohex_8(113880195+s));
	  lr_output_message(">>>>>>>>>>>>>>>Buffer07: %s",buffer_1);

	  //组装case3
	  strcat(buffer_1,inttohex_8(22602329+s));
	  lr_output_message(">>>>>>>>>>>>>>>Buffer08: %s",buffer_1);

	  //组装case4
	  strcat(buffer_1,inttohex_4(174+s));
	  lr_output_message(">>>>>>>>>>>>>>>Buffer09: %s",buffer_1);
	 }

	Hex_val_1 = Hex_values(buffer_1,2);
	CRC8_1 = Checksum_CRC8(Hex_val_1,strlen(buffer_1)/2);
	lr_output_message(">>>>CRC8_1>>>>>%x ",CRC8_1);
	//将CRC8校验值,转为2位数的16进制字符串
	sprintf(cacr8_values1, "%02x", (int)CRC8_1);
	//组装Crc8的校验值
	strcat(buffer_1,cacr8_values1);
	//将组装的buffer_1,转为LR识别的请求格式,比如"\xE5"
	send_buffer_val = send_buffer(buffer_1);
	lr_output_message(">>>最终send_buffer>>>>>%s ",send_buffer_val);

	 lr_save_string(send_buffer_val,"Param_data");
	 lr_save_int(strlen(lr_eval_string("<Param_data>"))/4,"Param_length");
     lrs_send("socket6", "buf5", LrsLastArg);
	 lrs_receive("socket6", "buf6", LrsLastArg);
	 lrs_get_last_received_buffer("socket6", &Data, &NumberOfBytes); 

	 if(NumberOfBytes == 8){
		lr_end_transaction("post", LR_PASS);
	 }else{
		 	lr_output_message(">>>最终buffer2>>>>>%s ",buffer_2);
		 	lr_output_message(">>>>CRC8_2>>>>>%x ",CRC8_2);
		lr_end_transaction("post", LR_FAIL);
	 }
	 
	 free(cacr8_values1);
	 free(Hex_val_1);
	 lrs_free_buffer(Data);

    return 0;
}



#include "lrs.h"

vuser_end()
{
	lrs_close_socket("socket6");
    lrs_cleanup();

    return 0;
}

结果:

Action.c(119): >>>>CRC8_1>>>>>98 
Action.c(124):>>>>buffer1:

010b0701c06438363833343530333134323635393638393836307a7a7a7a7a7a7a7a7a7a7a7a7a7a7a0a5b6d330f7806c9ac830158e25900ae006905f200000509000000900000009b0002e1d8019c010b00e75b6d33107806c9ac840158e25a00af006a05f30000050a000000910000009c0002e1d9019d010c00e85b6d33117806c9ac850158e25b00b0006b05f40000050b000000920000009d0002e1da019e010d00e95b6d33127806c9ac860158e25c00b1006c05f50000050c000000930000009e0002e1db019f010e00ea5b6d33137806c9ac870158e25d00b2006d05f60000050d000000940000009f0002e1dc01a0010f00eb5b6d33147806c9ac880158e25e00b3006e05f70000050e00000095000000a00002e1dd01a1011000ec5b6d33157806c9ac890158e25f00b4006f05f80000050f00000096000000a10002e1de01a2011100ed5b6d33167806c9ac8a0158e26000b5007005f90000051000000097000000a20002e1df01a3011200ee5b6d33177806c9ac8b0158e26100b6007105fa0000051100000098000000a30002e1e001a4011300ef5b6d33177806c9ac8c0158e26200b7007205fb0000051200000099000000a40002e1e101a5011400f098 

Action.c(135): >>>最终send_buffer:

\x01\x0b\x07\x01\xc0\x64\x38\x36\x38\x33\x34\x35\x30\x33\x31\x34\x32\x36\x35\x39\x36\x38\x39\x38\x36\x30\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x0a\x5b\x6d\x33\x0f\x78\x06\xc9\xac\x83\x01\x58\xe2\x59\x00\xae\x00\x69\x05\xf2\x00\x00\x05\x09\x00\x00\x00\x90\x00\x00\x00\x9b\x00\x02\xe1\xd8\x01\x9c\x01\x0b\x00\xe7\x5b\x6d\x33\x10\x78\x06\xc9\xac\x84\x01\x58\xe2\x5a\x00\xaf\x00\x6a\x05\xf3\x00\x00\x05\x0a\x00\x00\x00\x91\x00\x00\x00\x9c\x00\x02\xe1\xd9\x01\x9d\x01\x0c\x00\xe8\x5b\x6d\x33\x11\x78\x06\xc9\xac\x85\x01\x58\xe2\x5b\x00\xb0\x00\x6b\x05\xf4\x00\x00\x05\x0b\x00\x00\x00\x92\x00\x00\x00\x9d\x00\x02\xe1\xda\x01\x9e\x01\x0d\x00\xe9\x5b\x6d\x33\x12\x78\x06\xc9\xac\x86\x01\x58\xe2\x5c\x00\xb1\x00\x6c\x05\xf5\x00\x00\x05\x0c\x00\x00\x00\x93\x00\x00\x00\x9e\x00\x02\xe1\xdb\x01\x9f\x01\x0e\x00\xea\x5b\x6d\x33\x13\x78\x06\xc9\xac\x87\x01\x58\xe2\x5d\x00\xb2\x00\x6d\x05\xf6\x00\x00\x05\x0d\x00\x00\x00\x94\x00\x00\x00\x9f\x00\x02\xe1\xdc\x01\xa0\x01\x0f\x00\xeb\x5b\x6d\x33\x14\x78\x06\xc9\xac\x88\x01\x58\xe2\x5e\x00\xb3\x00\x6e\x05\xf7\x00\x00\x05\x0e\x00\x00\x00\x95\x00\x00\x00\xa0\x00\x02\xe1\xdd\x01\xa1\x01\x10\x00\xec\x5b\x6d\x33\x15\x78\x06\xc9\xac\x89\x01\x58\xe2\x5f\x00\xb4\x00\x6f\x05\xf8\x00\x00\x05\x0f\x00\x00\x00\x96\x00\x00\x00\xa1\x00\x02\xe1\xde\x01\xa2\x01\x11\x00\xed\x5b\x6d\x33\x16\x78\x06\xc9\xac\x8a\x01\x58\xe2\x60\x00\xb5\x00\x70\x05\xf9\x00\x00\x05\x10\x00\x00\x00\x97\x00\x00\x00\xa2\x00\x02\xe1\xdf\x01\xa3\x01\x12\x00\xee\x5b\x6d\x33\x17\x78\x06\xc9\xac\x8b\x01\x58\xe2\x61\x00\xb6\x00\x71\x05\xfa\x00\x00\x05\x11\x00\x00\x00\x98\x00\x00\x00\xa3\x00\x02\xe1\xe0\x01\xa4\x01\x13\x00\xef\x5b\x6d\x33\x17\x78\x06\xc9\xac\x8c\x01\x58\xe2\x62\x00\xb7\x00\x72\x05\xfb\x00\x00\x05\x12\x00\x00\x00\x99\x00\x00\x00\xa4\x00\x02\xe1\xe1\x01\xa5\x01\x14\x00\xf0\x98\x4e 
 

难点和解决思路:

1、了解TCP或UDP协议,细心观察TCP/UDP协议通讯过程中数据变化,比如:wareshark等底层抓包工具

2、了解CRC校验,并在CRC校验前,所有16进制数据,都需要转成16进制数组

3、字符串或数字如何转为16进制字符串,比如:数据太长,itoa和sprintf无法转,就需要一个字符的转

4、要了解lr发出socket请求时的格式如何,所以这里最终组装的16进制字符串,转为lr能send出去的格式

5、最终要是敢于尝试和总结

6、本次测试脚本开发时间紧张,加上能力有限,所以还有优化和不足之处,不喜请喷。

猜你喜欢

转载自blog.csdn.net/zouxiongqqq/article/details/81563650