用LoadRunner編寫socket應用的測試指令碼

idba發表於2009-10-02
  LoadRunner提供了很好的對socket應用的支援,使用者可以通過錄制方法完全獲得客戶端傳送和接收的資料,然後在錄製的基礎上對相應的資料進行引數化和關聯等處理。

        但在有些情況下(例如,客戶端程式沒有windows上的版本),我們就很難通過錄制達成生成指令碼的目標了。但如果我們能夠完全知曉服務端和客戶端的互動過程,完全手工編寫一個測試指令碼也並不是一件特別困難的事情。

       在本文中,我們以一個實際的例子說明如何根據服務端和客戶端互動的過程,用LoadRunner自行編寫相應的指令碼。

        以下是服務端工作執行緒的程式碼:
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gtDWORD WINAPI mythread( LPVOID lpParameter)    //客戶執行緒
{
    
struct My my;
    memcpy(
&my,lpParameter,sizeof(My));    
    printf(
"One client connect!\n");
    
char str1[1024];            //接收字串
    char str2[1024];
                        
    
int i;
    i
=recv(my.skt,str1,sizeof(str1),0);    //接收客戶請求
    str1[i]=0;

    
char *filename;
    filename
=new char[255];
    
for(int j=2;j<i;j++)            //獲得檔名
    {
        filename[j
-2]=str1[j];
    }
    filename[i
-2]=0;
   

    
if (str1[0]=='S')
    {
        printf(
"The file name : %s\n",filename);
        ofstream 
out(filename);                //創檔案流   
        if (!out)
        {
            printf(
"cannot open file.\n");        //檔案是否正確開啟,開啟錯誤則退出
            send(my.skt,"q",1,0);            //向客戶傳送退出資訊
            closesocket(my.skt);            //解除客戶連線;
            return 0;
        }
        str2[
0]='O';                       
        str2[
1]='K';
        str2[
2]=0;
        send(my.skt,str2,strlen(str2),
0);        //回覆OK資訊

        i
=recv(my.skt,str1,sizeof(str1),0);        //接收檔案長度
        str1[4]=0;
       
        
int len;
        len
=str1[0]*1000+str1[1]*100+str1[2]*10+str1[3];
        printf(
"The File lenght is: %d Byte\n",len);
       
        
for(int j=0;j<len;j++)
            {
                
char str[1];
                i
=recv(my.skt,str,sizeof(str),0);//接收檔案,按位元組接收,接收字串為2個位元組
                str[i]=0;
                
out.put(str[0]);
            }

        
out.close();                    //關閉檔案
        printf("over!One client quit!\n");        //接收檔案完畢
        closesocket(my.skt);                //解除此客戶連線
        return 0;
    }

    
if (str1[0]=='R')
    {       
       
        ifstream 
in(filename);
        
if (!in)
        {
            printf(
"cannot open file or file not exist.\n");    //檔案是否正確開啟,開啟錯誤則退出
            send(my.skt,"q",1,0);                    //向客戶傳送退出資訊
            closesocket(my.skt);                    //解除客戶連線;
            return 0;
        }
        
char ch;
        
int len=0;
        
while(in.get(ch))
        {
            len
++;                            //get file lenght
        }
        
in.close();
        str2[
0]='O';
        str2[
1]='K';
        str2[
2]=len/1000;                       
        str2[
3]=(len%1000)/100;
        str2[
4]=(len%100)/10;
        str2[
5]=len%10;
        printf(
"%s",str2);
        send(my.skt,str2,
6,0);                        //發OK+檔案長度

        
in.open(filename);
        
if (!in)
        {
            printf(
"cannot open file or file not exist.\n");    //檔案是否正確開啟,開啟錯誤則退出
            send(my.skt,"q",1,0);                    //向客戶傳送退出資訊
            closesocket(my.skt);                    //解除客戶連線;
            return 0;
        }

        
while(in.get(ch))                        //發檔案
        {               
            
char str[1];
            strcpy(str,
"");
            str[
0]=ch;
            str[
1]=0;
            send(my.skt,str,
1,0);                    //傳送一個字元
        }
        
in.close();
        printf(
"over,One client quit!\n");                //傳輸檔案完畢
        closesocket(my.skt);                        //解除此客戶連線
        return 0;
    }

    printf(
"Bad command!\n");
    closesocket(my.skt);
    
return 0;
}

        從這段程式碼中可以看到,當客戶端和服務端建立連線後,客戶端會先向服務端傳送一個請求,該請求的第一個位元組是大寫的“S”或是“R”,分別向服務端寫檔案或是從服務端讀取檔案。從第三個位元組開始,後面的內容是請求檔案的檔名。

        服務端在接收到客戶端的請求後,根據請求的型別,如果是“S”,則開啟指定的檔案,並返回一個字串“OK”;如果是“R”,則開啟指定的檔案並向客戶端傳送“OK”+“檔案長度”。

        隨後,如果是“S”,則由客戶端傳送寫入的檔案長度和檔案內容給服務端;如果是“R”,則向客戶端傳送檔案的內容。

        到此我們已經完全明瞭了客戶端和服務端的互動過程,因此,我們可以嘗試在LR中建立一個指令碼使用者模擬客戶端行為。

        下面我們以“S”的處理過程為例編寫指令碼。

        1、開啟VUGen應用;
        2、新建指令碼,選擇“windows sockets”協議,不需錄製;
        3、在Action Section中增加以下內容:
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt    //建立到服務端的連線
    lrs_create_socket("socket1","TCP","RemoteHost=127.0.0.1:8000",LrsLastArg);
   
    
//傳送“S”和檔名
    lrs_send("socket1""buf0", LrsLastArg);
    lrs_receive(
"socket1""buf1", LrsLastArg);
   
    
//傳送要寫入的資料的長度
    lrs_send("socket1""buf2", LrsLastArg);

    
//傳送資料內容
    lrs_send("socket1""buf3", LrsLastArg);
   
    
//關閉連線
    lrs_close_socket("socket1");
   
        4、這樣就成功的描述了整個互動過程,但還沒有給出實際要傳送的資料。在採用“Windows Sockets”協議的指令碼中,實際傳送的資料存放在data.ws Section中,因此,開啟該Section,直接輸入:
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gtsend  buf0 7
    
"S"
    
"\x00"
    
"1.txt"

recv buf1 
2
    
"OK"

send buf2 
3
    
"\x00"
    
"\x00"
    
"\x02"
    
"\x00"

send buf3 
20
    
"12345678901234567890"

        每個傳送和接收的資料包在這裡都有登記,“send”和“recv”表示資料的方向;“buf0”等表示資料包的描述,和指令碼中的內容對應;接下來的一個整數表示資料包的長度;然後是資料包的內容,“\x00”表示16進位制的00。

        該指令碼描述了客戶端向服務端請求寫入一個檔案1.txt,檔案內容為“12345678901234567890”的過程。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1384/viewspace-615952/,如需轉載,請註明出處,否則將追究法律責任。

相關文章