LoadRunner testing TCP protocol server performance

Source: Internet
Author: User
Tags 04x

Recently on the server's performance interest, so began to study for a while loadrunner how to do the TCP protocol interactive server performance testing, LoadRunner is not very familiar with, so the beginning also took some detours, will learn the process of recording down, for future reference it.

TCP protocol server performance testing, I think everyone will choose LoadRunner winsocket protocol to test, I also use this way. The following is a record of how performance testing is done using this protocol.

1. Test with DLL file mode

Because the DLL file for the client that is connected to the server I have at hand, and its corresponding header file also has, so the first think is to use LoadRunner call DLL file way to implement performance testing. Because this is a simple method, it is easy to get started without having to know a lot of LoadRunner winsocket related functions. The following code is the code that was initially written in the DLL file:

Vuser_init.c

Vuser_init () {    lrs_startup (257); Lr_load_dll ("InnoVSSBASClient.dll");    Lr_load_dll ("Ole32.dll");    return 0;}

Action.c

#include "lrs.h" #include "def.h" Action () {char* Test;long handle;net_client_info info;int islogin;net_cross_info Crossinfo;net_vehcile_pass_info lrpassinfo = {0};net_vehcile_alarm_info Lralarminfo = {0};handle = InnoVSSBASClient_ Init (Null,null); strcpy (Info.clientid,guid_gen ()); strcpy (Info.serverip, "127.0.0.1"); info.serverport = 9300;strcpy (Info.username, "admin"); strcpy (Info.password, "admin"); Lr_start_transaction ("Tran_login_start"); IsLogin = Innovssbasclient_createconn (Handle,&info); if (islogin==1) {lr_end_transaction ("Tran_login_start", LR_AUTO); LR _output_message (Info.clientid); Lr_output_message ("Landing Success");//innovssbasclient_setcallbackfunc (Handle, INNOVSSBASCLIENTCALLBACK,1L); Lr_start_transaction ("Tran_addcross_start"); strcpy (Crossinfo.crossid,lr_eval_           String ("{crossid}"); Innovssbasclient_addcrossinfo (Handle,&crossinfo); Lr_end_transaction ("Tran_addcross_start", LR_AUTO);} Else{lr_end_transaction ("Tran_login_start", Lr_fail); Lr_output_message (Info.clientid); Lr_output_messagE ("Login Failed");}    while (1) {sleep (100);} return 0;}
The DLL file required by the program is loaded in Vuser_init, InnoVSSBASClient.dll is the DLL file for the client connected to the server, and Ole32.dll is the DLL file that needs to be loaded for string functions in the program (such as strcpy, etc.).

The action is the body code of the performance test. This code is a total of two operations: Login and add intersection information to do the transaction monitoring.

The use of DLL files in the way of testing the simple sequence of operation is very suitable, but this client also has a function is needed to deal with the server real-time transmission of the vehicle and other information functions, in the test server-side functions, but also need to simulate the function of the client's callback function, but The way to define the callback function was not found in LoadRunner, so it was forced to abandon this simple performance test. In this want to ask LoadRunner Daniel, how to LoadRunner in the first callback function?

The above method does not realistically simulate the situation of the client, so the following will be recorded using the LoadRunner itself WinSocket function to test.

2. Test with LoadRunner's WinSocket function

I first on the source code, and then explain each:

Def.h//This file is an external file, where you define a custom function

char* Guid_gen () {//Generate GUID method typedef struct _GUID {unsigned long data1;unsigned short Data2;unsi gned short data3;unsigned char data4[8];} GUID; GUID M_guid;char Buf[50];char pnamestr[50]; CoCreateGuid (&AMP;M_GUID);//define Output format//sprintf (buf, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",//Uppercase// sprintf (buf, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",//lowercase sprintf (buf, "%08lx-%04x-%04x-%02x%02x-%0 2x%02x%02x%02x%02x%02x ",//lowercase%08lx-%04x%04x-%02x%02x%02x%02x-%02x%02x%02x%02xm_guid. Data1, M_guid. Data2, M_guid. Data3,m_guid. Data4[0], M_guid. Data4[1], M_guid. DATA4[2], M_guid. Data4[3],m_guid. DATA4[4], M_guid. DATA4[5], M_guid. DATA4[6], M_guid. DATA4[7]);//lr_save_string (buf, paramname);//sprintf (Pnamestr, "{%s}", paramname); return lr_eval_string (BUF);}      char* Join (Char *s1, char *s2) {char *result = (char*) malloc (strlen (S1) +strlen (S2) +1);//+1 for the Zero-terminator In real code, would check for errors in malloc here if (result = = NULL)Exit (1);      strcpy (result, S1);        strcat (result, S2);  return result; }//string substitution function.//can replace all the strings to be replaced, the replaced string and the replacement string is not necessarily the same length.//Pinput-input string.//Poutput-The output string, to ensure enough space to store the replaced string.//PSRC-to be replaced  substrings, such as%user%//pDst-the string to be replaced, such as user1//Note: The above string must end with '/'.//void substitute (char *pinput, Char *poutput, Char *psrc,    Char *pdst) {char *pi, *PO, *p;    int Nsrclen, Ndstlen, Nlen;    A swim pointer to the input string.        PI = pinput;    A swim pointer to the output string.    PO = poutput;    Calculates the length of the replaced string and the replacement string.    Nsrclen = strlen (PSRC);     Ndstlen = strlen (pDst);       Find pi points to the position of the first occurrence of the replacement string in the strings and returns a pointer (null is returned if not found).    p = (char*) strstr (pi, PSRC);        if (p) {//found.            while (p) {//calculates the length of the string that is replaced by the strings front.            Nlen = (int) (P-PI);            Copy to the output string.            memcpy (PO, pi, Nlen);            memcpy (PO + nlen, pDst, Ndstlen);            Skips a string that is replaced.            PI = p + nsrclen;            Adjusts the pointer position to the output string.            PO = po + nlen + ndstlen;         Continue to find.   p = (char*) strstr (pi, PSRC);        }//Copy the remaining string.    strcpy (PO, pi);        } else {//is not found and is copied as-is.    strcpy (PO, pi); }}/* @param char* dest Target string, that is, the new string after replacement * @param const char* src source string, replaced String * @param const char* OLDSTR old substring, substring to be replaced * @param Const char* NEWSTR New substring * @param int len will be replaced by the first Len character */char *strreplace (char *dest, char *src, const char *OLDSTR, const C Har *newstr, size_t len) {//SUBSTRING position pointer char *needle;//temporary memory Area char *tmp;//if the strings are equal, return directly to Lr_output_message ("newstr:%s", newstr); if (strcmp (Oldstr, newstr) ==0) {return src;} Assign the source string address to the pointer dest, that is, both dest and Src point to the memory area of src Dest = src;//If a substring is found, and the substring position is within the range of the front len Substring, then it is returned directly while ((needle = (char *) Strstr (dest, Oldstr)) && (needle-dest <= len)) {//Allocate new space: +1 is to add end-of-string ' \ s ' Terminator tmp= (char*) malloc (strlen (dest) + (Strlen (NEWSTR)-strlen (OLDSTR)) +1);//Copy the data of the former Needle-dest memory space in SRC to arrstrncpy (tmp, dest, needle-dest);//Identify string end tmp [needle-dest]= '];//Connect arr and newstr, that is, attach newstr to the tail of arr, thus forming a new string (or character array) Arrstrcat (TMP, NEWSTR);//Put SRC from Oldstr sub-stringThe placed part and Arr are connected together to form a new string Arrstrcat (TMP, Needle+strlen (OLDSTR));//The memory allocated with malloc is copied to the pointer retvdest = (char *) strdup (TMP);// Frees the memory space allocated by malloc free (TMP); return dest;}

This file contains functions for two functions: one is how to generate a GUID, and one is how to replace a substring in a string.

Action.c

/********************************************************************* * Created by Mercury Interactive Windows Sockets Recorder * * Created on:tue Dec 30 16:04:06 *******************************************************************    **/#include "lrs.h" #include "def.h" Action () {int sendlogincount=0,sendcrosscount=0;    int loginindex,loginindex2;char* clientId = Guid_gen (); Char clientid2[100];char* clientid3;int Clientidlen; char* loginsrc = "<?xml version=\" 1.0\ "encoding=\" utf-8\ "? >\n<parament>\n" "<ClientId> $ClientId &L T;/clientid>\n "" <ServerIP> $IP </serverip>\n "" <ServerPort> $Port </serverport>\n "" <u sername></username>\n "<password></password>\n" "</Parament>"; char* loginstr;int loginstrlen;char* Loginstrlenhex;char loginstrlenstr[5];char send_loginheader[100]= "\\x12$Len\\x00\\x010"; char* Send_loginheaderf;char send_loginstr[1500]= "";//Add intersection related strings char* crosssrc= "<?xml version=\" 1.0\ "encodIng=\ "utf-8\"? >\n<parament>\n "" <ClientId> $ClientId </clientid>\n "" <CrossId> $CrossId & lt;/crossid>\n "</Parament>"; char* send_addcrossheader = "\\x12$Len\\x00\\x02"; char* crossid = Lr_eval_ String ("<db_crossId>"); char* Crossstr;char Send_crossstr[1700];char crossstrlenstr[5];int crossstrlen;char* Send_addcrossheaderf;int crossaddindex,crossaddindex2;strcpy (clientid2,lr_eval_string (clientId)); clientId3 = clientid;//Login Data Loginstr = Strreplace (loginstr,loginsrc, "$ClientId", Clientid,strlen (LOGINSRC)); loginstr = Strreplace (Loginstr,loginstr, "$IP", "127.0.0.1", strlen (LOGINSTR)); loginstr = Strreplace (Loginstr,loginstr, "$Port" , "9300", strlen (LOGINSTR)), Lr_output_message ("loginstr:%s", loginstr); Loginstrlen = strlen (loginstr) +1;//lr_output    _message ("loginstrlen:%d", Loginstrlen);//itoa (loginstrlen,loginstrlenstr,16); sprintf (Loginstrlenstr, "%x", Loginstrlen);//lr_output_message ("loginstrlenstr:%s", loginstrlenstr); if (strlen ( LOGINSTRLENSTR) ==2) {Chartmph[5];strcpy (TMPH,LOGINSTRLENSTR); strcpy (Loginstrlenstr, "\\x00\\x00\\x00\\x"); strcat (loginstrlenstr,tmph);} Else{char Tmph[5];char tmpd[5];strcpy (TMPH,LOGINSTRLENSTR); strcpy (tmph+1, "n"); strcpy (Tmpd,loginstrlenstr+strlen (LOGINSTRLENSTR)-2); strcpy (Loginstrlenstr, "\\x00\\x00\\x0"); strcat (loginstrlenstr,tmph); Strcat (Loginstrlenstr, "\\x"); strcat (LOGINSTRLENSTR,TMPD);//lr_output_message ("tmph:%s", TmpH);//lr_output_message ("tmpd:%s", TmpD);} Lr_output_message ("loginstrlenstr:%s", loginstrlenstr); send_loginheaderf = Strreplace (send_loginHeaderf,send_ Loginheader, "$Len", Loginstrlenstr,strlen (Send_loginheader))//lr_output_message ("send_loginheader:%s", Send_ LOGINHEADERF); strcpy (Send_loginstr,send_loginheaderf);//lr_output_message ("send_loginstr:%s", send_loginStr); For (Loginindex=0,loginindex2=strlen (SEND_LOGINSTR); Loginindex<strlen (LOGINSTR); loginindex++,loginindex2++) { Char loginhex[5];sprintf (Loginhex, "\\x%.2X", Loginstr[loginindex]);//strcat (Send_loginbody,loginhex); strcat (send _loginstr+loginIndex2,loginhex);} strcat (Send_loginstr+loginindex2, "\\x0A"); Lr_output_message ("send_loginstr:%s", send_loginstr);//Create a TCP connection Lr_    Start_transaction ("login"); Lrs_create_socket ("Socket0", "TCP", "localhost=0", "remotehost=127.0.0.1:1234", Lrslastarg); for (sendlogincount = 0; Sendlogincount < 10;sendlogincount++) {//lr_output_message ("send_loginstr:%s", send_loginstr); lr_output_message ("sendlogincount:%d", Sendlogincount), Lrs_set_send_buffer ("Socket0", Send_loginstr,strlen (SEND_LOGINSTR)); Lrs_ Send ("Socket0", "buf0", Lrslastarg) lrs_receive ("Socket0", "Buf1", Lrslastarg); {char* login_recv;int login_recvlen;int i;lrs_get_last_received_buffer ("Socket0", &login_recv,&login_ Recvlen), if (login_recvlen!=0) {lr_end_transaction ("login", Lr_auto); Lr_output_message ("%s", login_recv+15);// Add junction lr_output_message ("clientid3:%s", Lr_eval_string (CLIENTID2)); crossstr = Strreplace (CROSSSTR,CROSSSRC, "$ ClientId ", Clientid3,strlen (CROSSSRC)); crossstr = Strreplace (Crossstr,crossstr," $CrossId ", Crossid,strlen (crossstr )); Lr_output_message ("crossstr:%s", crossstr), Crossstrlen = strlen (crossstr) +1;sprintf (crossstrlenstr, "%x", Crossstrlen), if (strlen (CROSSSTRLENSTR) ==2) {char tmph[5];strcpy (TMPH,CROSSSTRLENSTR); strcpy (crossstrlenstr, "\ \ X00\\x00\\x00\\x "); strcat (crossstrlenstr,tmph);} Else{char Tmph[5];char tmpd[5];strcpy (TMPH,CROSSSTRLENSTR); strcpy (tmph+1, "n"); strcpy (Tmpd,crossstrlenstr+strlen (CROSSSTRLENSTR)-2); strcpy (Crossstrlenstr, "\\x00\\x00\\x0"); strcat (crossstrlenstr,tmph); Strcat (Crossstrlenstr, "\\x"); strcat (CROSSSTRLENSTR,TMPD);//lr_output_message ("cross_tmph:%s", TmpH);//lr_output_message ("cross_tmpd:% S ", TmpD);} Lr_output_message ("crossstrlenstr:%s", crossstrlenstr); send_addcrossheaderf = Strreplace (Send_addCrossHeaderf, Send_addcrossheader, "$Len", Crossstrlenstr,strlen (Send_addcrossheader));//lr_output_message ("Send_ Addcrossheaderf:%s ", Send_addcrossheaderf); strcpy (Send_crossstr,send_addcrossheaderf);//lr_output_message (" Send _crossstr:%s ", send_crossstr); for (Crossaddindex=0,crossaddindex2=strlen (SEND_CROSSSTR); Crossaddindex<strlen (CROSSSTR); crossaddindex++,crossaddindex2++) {char crosshex[5];sprintf (CrossHex, " \\x%.2X ", Crossstr[crossaddindex]);//strcat (Send_loginbody,loginhex); Strcat (Send_crossstr+crossaddindex2, Crosshex);} strcat (Send_crossstr+crossaddindex2, "\\x0A"); Lr_output_message ("send_crossstr:%s", send_crossstr);//lr_output_ Message ("send_loginstr:%s", send_loginstr); Lr_start_transaction ("Addcross"); for (Sendcrosscount=0;sendcrosscount <10;sendcrosscount++) {lr_output_message ("send_crossstr:%s", send_crossstr); Lr_output_message ("SendCrossCount :%d ", sendcrosscount); Lrs_set_send_buffer (" Socket0 ", Send_crossstr,strlen (SEND_CROSSSTR)); Lrs_send (" Socket0 "," Buf0 ", Lrslastarg); Lrs_receive (" Socket0 "," Buf1 ", Lrslastarg); {char* cross_recv;int cross_recvlen;lrs_get_last_received_buffer ("Socket0", &cross_recv,&cross_recvlen); if (cross_recvlen!=0) {lr_end_transaction ("Addcross", Lr_auto); Lr_output_message ("cross_recv:%s", cross_recv+15); break;} Else{//lr_end_transaction ("Addcross", Lr_fail);}}if (sendcrosscount>10) {lr_end_transaction ("Addcross", Lr_fail);} break;} Else{//lr_end_transaction ("Login", Lr_fail);}} if (sendlogincount>10) {lr_end_transaction ("login", lr_fail);} while (1) {char* recv;int recvlen;lrs_receive ("Socket0", "buf3", Lrslastarg); Lrs_get_last_received_buffer ("Socket0", &recv,&recvlen), if (recvlen!=0) {lr_output_message ("recv:%s", recv+15);}    else{}} lrs_close_socket ("Socket0"); return 0;}
The above code of the specific business is not introduced, I would like to introduce in this piece of code should be noted in the area:

1) This code simulates the 16-binary data sent by the client, and here is a reference to the character, how the string is converted into a 16 binary string in LoadRunner.

The characters in LoadRunner 16 are denoted by the preceding ' \x ' method, such as the 16 binary 0xAB, then the loadrunner need to be represented as ' \xab ';

Shaping to 16 binary string: sprintf (Loginstrlenstr, "%x", Loginstrlen);

16 binary string converted to the approved 16 string in LoadRunner:

For (Loginindex=0,loginindex2=strlen (SEND_LOGINSTR); Loginindex<strlen (LOGINSTR); loginindex++,loginindex2++) { Char loginhex[5];sprintf (Loginhex, "\\x%.2X", Loginstr[loginindex]);//strcat (Send_loginbody,loginhex); strcat (send _loginstr+loginindex2,loginhex);}
This section uses this method to convert each character of the string "ABCD" into a loadrunner-approved 16-string (for example: the character "a" translates to "\x61")

This method is a stupid method, do not know in the LoadRunner do not have the function to do the string 16 binary conversion it?

2) LoadRunner do the basic steps of WinSocket test:

/********************************************************************* * Created by Mercury Interactive Windows Sockets Recorder * * Created on:mon Dec 29 09:01:03 *******************************************************************    **/#include "lrs.h" Action () {int i; Char *buffer;//defines the character pointer int numberofbytes;//defines the type of int variable to save length//This is the first step initializes a socket Lrs_create_socket ("Socket0", "   TCP "," localhost=0 "," remotehost=127.0.0.1:1234 ", Lrslastarg); Lr_start_transaction (" send "); Here is the second step, through the establishment of the SOCKET1 will be buf1 in the data sent to the remote MM-7QL3Z0JYUJN6 user, Port 2425lrs_send ("Socket0", "Buf1", Lrslastarg);    Output buffer data size lrs_send ("socket0", buffer, lrslastarg); Receive the returned data from Buf2 lrs_receive ("Socket0", "Buf2", lrslastarg);//Get Buffer data lrs_get_buffer_by_name ("Buf2", &buffer, &numberofbytes);//output buffer data size lr_output_message ("The buffer's size is:%d/n", numberofbytes); Lr_output_message (        buffer); Lr_end_transaction ("Send", Lr_auto);    The third step closes the release socket connection Lrs_close_socket ("Socket0"); return 0;}
The comments on the above code are clear, but it is important to note that the BUF in Lrs_send in LoadRunner need to be defined in data.ws and not as a string defined in the program.

Data.ws

; Wsrdata 2 1send buf0recv buf1 101recv buf2 210recv buf3 300-1

3) Explanation of some functions of winsocket programming

①lrs_set_send_buffer ("Socket0", Send_loginstr,strlen (SEND_LOGINSTR));

Lrs_set_send_buffer the string defined in the program into the data.ws first defined send BUFX, as defined in the above data.ws as buf0, it is buf0 in its way, no matter how many times it is called, is put into buf0.

②lrs_receive ("Socket0", "Buf1", Lrslastarg);

Lrs_get_last_received_buffer ("Socket0", &login_recv,&login_recvlen);

The length of the BUF1 definition is not the same as the actual received length, LoadRunner only outputs a warning message in the output, but does not affect the actual received data. Warning message: Mismatch in buffer's length (expected 101 bytes, 222 bytes actually received, difference in 121 bytes)

The LoadRunner test code can be downloaded here.

LoadRunner testing TCP protocol server performance

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.