SOCKET测试脚本,附带源码和服务端

LoadRunner编写socket应用的测试脚本
        LoadRunner
提供了很好的对socket应用的支持,用户可以通过录制方法完全获得客户端发送和接收的数据,然后在录制的基础上对相应的数据进行参数化和关联等处理。
但在有些情况下(例如,客户端程序没有windows上的版本),我们就很难通过录制达成生成脚本的目标了。但如果我们能够完全知晓服务端和客户端的交互过程,完全手工编写一个测试脚本也并不是一件特别困难的事情。
在本文中,我们以一个实际的例子说明如何根据服务端和客户端交互的过程,用LoadRunner自行编写相应的脚本。
以下是服务端工作线程的代码:
DWORD 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=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=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中增加以下内容:
    //
建立到服务端的连接
    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,直接输入:
send  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”的过程。

posted on 2008-12-22 18:32  starspace  阅读(692)  评论(0编辑  收藏  举报

导航