loadrunner测试TCP协议服务器性能

最近对服务器的性能感兴趣,于是开始研究了一阵子loadrunner如何做采用TCP协议交互的服务器的性能测试,对loadrunner不是很熟悉,所以一开始也走了一些弯路,现将学习的过程记录下来,为以后做参考吧。

TCP协议的服务器的性能测试,我想大家都会选择loadrunner的winsocket协议进行测试,我也是采用此种方式。下面将逐一记录如何使用此协议做性能测试。

1.采用DLL文件方式进行测试

由于与服务器连接的客户端的DLL文件我手头有,同时其对应的头文件也有,所以一开始试想的是采用loadrunner调用DLL文件的方式来实现性能测试。因为这种方式简单,不需了解很多loadrunner的winsocket的相关函数,容易上手。下面的代码即是采用DLL文件初步编写的代码:

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("登陆成功");

		//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("登陆失败");
	}

    while(1)
	{
		sleep(100);
	}
    return 0;
}

vuser_init中加载了程序所需要的DLL文件,InnoVSSBASClient.dll为与服务器连接的客户端的DLL文件,而ole32.dll为程序中的字符串函数(比如strcpy等)需要加载的DLL文件。

action中则是性能测试的主体代码。本代码一共对两个操作:登录和添加路口信息做了事务监控。

采用DLL文件的方式针对测试简单的顺序的操作很适用,但是本客户端还有个功能是需要处理服务器实时传输的过车等信息的功能,即在测试服务器端功能的时候,还需要模拟出客户端的回调函数的功能,但是在loadrunner中没有找到定义回调函数的方式,于是不得不放弃这种简单的性能测试的方式。在此想向loadrunner的大牛问一下,如何在loadrunner中第一回调函数呢?

上面的方式不能真实的模拟客户端的情况,于是下面会记录采用loadrunner本身的winsocket函数进行测试。

2.采用loadrunner的winsocket函数做测试

我先上源码,然后逐一讲解:

def.h //本文件是外部文件,在此用于定义自定义函数

char* guid_gen(){                         //生成GUID方法
	typedef struct _GUID    {
		unsigned long Data1;
		unsigned short Data2;
		unsigned short Data3;
		unsigned char Data4[8];
	} GUID;
	GUID m_guid;
	char buf[50];
	char pNameStr[50];
	CoCreateGuid(&m_guid);
	// 定义输出格式
	//sprintf (buf, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", // 大写
	//sprintf (buf, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",// 小写
	sprintf (buf, "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",// 小写%08lx-%04x%04x-%02x%02x%02x%02x-%02x%02x%02x%02x
	m_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 you would check for errors in malloc here
    if (result == NULL) exit (1);  

    strcpy(result, s1);
    strcat(result, s2);  

    return result;
}

// 字符串替换函数.
// 能替换所有的要替换的字符串,被替换的字符串和替换的字符串不一定一样长.
// pInput - 输入字符串.
// pOutput - 输出字符串, 要保证足够的空间可以存储替换后的字符串.
// pSrc - 要被替换的子字符串, 比如%user%
// pDst - 要替换成的字符串, 比如user1
// 注意:以上的字符串均要以'\0'结尾.
//
void Substitute(char *pInput, char *pOutput, char *pSrc, char *pDst)
{
    char    *pi, *po, *p;
    int     nSrcLen, nDstLen, nLen;

    // 指向输入字符串的游动指针.
    pi = pInput;
    // 指向输出字符串的游动指针.
    po = pOutput;
    // 计算被替换串和替换串的长度.
    nSrcLen = strlen(pSrc);
    nDstLen = strlen(pDst);

    // 查找pi指向字符串中第一次出现替换串的位置,并返回指针(找不到则返回null).
    p = (char*)strstr(pi, pSrc);
    if(p)
    {
        // 找到.
        while(p)
        {
            // 计算被替换串前边字符串的长度.
            nLen = (int)(p - pi);
            // 复制到输出字符串.
            memcpy(po, pi, nLen);
            memcpy(po + nLen, pDst, nDstLen);
            // 跳过被替换串.
            pi = p + nSrcLen;
            // 调整指向输出串的指针位置.
            po = po + nLen + nDstLen;
            // 继续查找.
            p = (char*)strstr(pi, pSrc);
        }
        // 复制剩余字符串.
        strcpy(po, pi);
    }
    else
    {
        // 没有找到则原样复制.
        strcpy(po, pi);
    }
}

/* @param char* dest 目标串,也就是替换后的新串
* @param const char* src 源字符串,被替换的字符串
* @param const char* oldstr 旧的子串,将被替换的子串
* @param const char* newstr 新的子串
* @param int len 将要被替换的前len个字符*/
char *strreplace(char *dest, char *src, const char *oldstr, const char *newstr, size_t len)
{
	//子串位置指针
	char *needle;
	//临时内存区
	char *tmp;

	//如果串相等,则直接返回
	lr_output_message("newStr:%s",newstr);
	if(strcmp(oldstr, newstr)==0)
	{
		return src;
	}

	//把源串地址赋给指针dest,即让dest和src都指向src的内存区域
	dest = src;
	//如果找到子串, 并且子串位置在前len个子串范围内, 则进行替换, 否则直接返回
	while((needle = (char *) strstr(dest, oldstr)) && (needle -dest <= len))
	{
		//分配新的空间: +1 是为了添加串尾的'\0'结束符
		tmp=(char*)malloc(strlen(dest)+(strlen(newstr)-strlen(oldstr))+1);
		//把src内的前needle-dest个内存空间的数据,拷贝到arr
		strncpy(tmp, dest, needle-dest);
		//标识串结束
		tmp[needle-dest]='\0';
		//连接arr和newstr, 即把newstr附在arr尾部, 从而组成新串(或说字符数组)arr
		strcat(tmp, newstr);
		//把src中 从oldstr子串位置后的部分和arr连接在一起,组成新串arr
		strcat(tmp, needle+strlen(oldstr));
		//把用malloc分配的内存,复制给指针retv
		dest = (char *)strdup(tmp);
		//释放malloc分配的内存空间
		free(tmp);
	}
	return dest;
}

本文件包含了两种功能的函数:一个是如何生成guid,一个是如何替换字符串中的子串。

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</ClientId>\n"
						"    <ServerIP>$IP</ServerIP>\n"
						"    <ServerPort>$Port</ServerPort>\n"
						"    <Username></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]="";

	//添加路口相关字符串
	char* crossSrc= "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<Parament>\n"
						"    <ClientId>$ClientId</ClientId>\n"
						"    <CrossId>$CrossId</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;

	//登陆数据
	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)
	{
		char tmpH[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,"\0");
		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);

	//创建TCP连接
	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);

				//添加路口
				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,"\0");
					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;
}

上面代码的具体业务就不介绍了,在此我介绍一下在该片代码中应该注意的地方:

1)本代码模拟了客户端所发的16进制的数据,在此提一下字符、字符串如何转换成loadrunner中的16进制的字符串。

在loadrunner中16进行的字符采用前面加’\x‘的方式表示,如16进制0xAB,则在loadrunner中需要表示为‘\xAB‘;

整形转为16进制字符串:sprintf(loginStrLenStr, "%X", loginStrLen);

16进制字符串转换为loadrunner中认可的16进制串:

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);
	}

本部分使用的是本方法,即将字符串“abcd"的的每个字符逐一转换成loadrunner认可的16进制串(如:字符”a"转换成"\x61“)

该方法是个笨方法,不知在loadrunner中有没有自带的函数做字符串的16进制转换呢?

2)loadrunner做winsocket测试的基本步骤:

/*********************************************************************
 * Created by Mercury Interactive Windows Sockets Recorder
 *
 * Created on: Mon Dec 29 09:01:03
 *********************************************************************/

#include "lrs.h"

Action()
{
    int i;
    char *buffer;//定义字符指针
    int numberOfBytes;//定义int型变量保存长度

    //这是第一步initializes a socket
    lrs_create_socket("socket0", "TCP", "LocalHost=0", "RemoteHost=127.0.0.1:1234",LrsLastArg);

	lr_start_transaction("send");
   //这里是第二步,通过建立的socket1将buf1中的数据发送给远端MM-7QL3Z0JYUJN6用户,端口2425
	lrs_send("socket0", "buf1",  LrsLastArg);

	//输出缓冲区数据大小
	lrs_send("socket0", buffer,  LrsLastArg);

    //从buf2中接收返回的数据
	lrs_receive("socket0", "buf2", LrsLastArg);

	//取得缓冲区数据
	lrs_get_buffer_by_name("buf2", &buffer, &numberOfBytes);
	//输出缓冲区数据大小
	lr_output_message("The buffer's size is: %d/n", numberOfBytes);
	lr_output_message(buffer);

	lr_end_transaction("send", LR_AUTO);

    //第三步关闭释放socket连接
    lrs_close_socket("socket0");

    return 0;
}

上面的代码的注释很明确了,不过需要注意一点的是,loadrunner中lrs_send中的缓存的buf需要在data.ws中定义,不能是程序中定义的字符串。

data.ws

;WSRData 2 1

send buf0
recv buf1 101
recv buf2 210
recv buf3 300

-1

3)对winsocket编程的一些函数的解释

①lrs_set_send_buffer("socket0",send_loginStr,strlen(send_loginStr));

lrs_set_send_buffer将程序中定义的字符串放入data.ws第一个定义的send bufx中,如上面的data.ws中定义的为buf0,则是将其方式buf0中,不管调用多少次,都是放入到buf0中。

②lrs_receive("socket0", "buf1", LrsLastArg);

lrs_get_last_received_buffer("socket0",&login_recv,&login_recvlen);

buf1定义的长度与实际接收的长度不一致没关系,loadrunner只会在输出中输出一个警告信息,但是不会影响实际接收的数据。警告信息为: Mismatch in buffer‘s length (expected 101 bytes, 222 bytes actually received, difference in 121 bytes)

该loadrunner测试代码在这里可以下载。

时间: 2024-12-23 14:46:45

loadrunner测试TCP协议服务器性能的相关文章

Loadrunner测试webservice协议总结

Loadrunner测试webservice协议总结 一.协议选择 1.打开Virtual user generator,新建脚本,选择webservice协议 2.当选择的协议不明确或者被测系统协议不明确时,使用loadrunner11自带的协议分析软件,文件->分析软件->分析应用程序,选择应用程序类型和路径确定即可,等待分析结果. 3.  协议选择完毕后,进入脚本创建界面 二.脚本创建 1.导入服务 管理服务->导入,输入被测服务的路径导入,确定 2.添加调用程序 1.添加服务调用

Nginx均衡TCP协议服务器案例

Nginx在企业运维中通常用来均衡HTTP协议,例如我们熟知的80.8080.8081等服务.因为大部分的服务都是http请求访问协议,那有时候需要用到TCP协议,如果来实现均衡呢? 默认nginx不支持tcp的负载均衡,需要打补丁,(连接方式:从客户端收到一个连接,将从本地新建一个连接发起到后端服务器.) 接下来正式配置Nginx均衡TCP: wget http://nginx.org/download/nginx-1.6.2.tar.gz wget https://github.com/ya

Loadrunner测试http接口的性能

作者:余水军 性能测试首选工具是loadrunner.然而,loadrunner在做接口测试时又不像web哪样可以直接录制脚本,可能就不知道怎么做了.其实,loadrunner做http的接口性能也很简单.在接到http接口的性能测试时,我们首先要了解这个接口是get类型的还是post类型的.然后我们分别来看看这两个类型的接口的测试方法. 一.get类型的接口 get类型的接口,其请求参数是附加在url中的,直接用web_ur发送请求即可,如: web_url("getname", ?

TCP 协议快被淘汰了,UDP 协议才是新世代的未来?

TCP 协议可以说是今天互联网的基石,作为可靠的传输协议,在今天几乎所有的数据都会通过 TCP 协议传输,然而 TCP 在设计之初没有考虑到现今复杂的网络环境,当你在地铁上或者火车上被断断续续的网络折磨时,你可能都不知道这一切可能都是 TCP 协议造成的.本文会分析 TCP 协议为什么在弱网环境下有严重的性能问题[^1]. 底层的数据传输协议在设计时必须要对带宽的利用率和通信延迟进行权衡和取舍,所以想要解决实际生产中的全部问题是不可能的,TCP 选择了充分利用带宽,为流量而设计,期望在尽可能短的

DICOM:基于JMeter+dcm4che2测试PACS服务器性能的解决方案(前篇)

背景: 目前对于传统WEB网站性能(压力/负载)的测试工具有很多,loadrunner.iperf.siege等,操作都比较简单,这里就不介绍了.然而对于医疗领域内的服务器,通常指的是DICOM服务器,提供满足DICOM3.0标准规定的各项DIMSE服务,诸如DIMSE-C(C-STORE.C-FIND.C-MOVE.C-ECHO).DIMSE-N(N-CREATE.N-DELETE)等等.倘若使用传统的压力测试工具会有几大局限性: 常见压力测试工具,通过模拟上千万用户实施并发负载及实时性能监测

基于TCP协议的服务器中转简易聊天

项目比较简单:主要使用了TCP传输协议.多线程和swing窗口,以及IO流读写. 功能:各窗口之间简单的收发信息,另外附加一个抖动的效果. 服务器代码: 1 package com.java; 2 3 import java.awt.Dimension; 4 import java.awt.Toolkit; 5 import java.awt.event.ActionEvent; 6 import java.awt.event.ActionListener; 7 import java.awt.

Ubuntu利用TCP协议来获取服务器时间

Linux利用TCP协议来获取服务器时间 这里使用Unix网络编程里面的一个小程序,该客户端建立一个到服务器的TCP连接,然后读取由服务器以直观可读格式简单地送回的当前时间和日期. #include "unp.h" int main(int argc, char **argv) { int sockfd, n; char recvline[MAXLINE + 1]; struct sockaddr_in servaddr; if (argc != 2) err_quit("u

简述tcp协议对http性能的影响及优化

当网站服务器并发连接达到一定程度时,你可能需要考虑服务器系统中tcp协议设置对http服务器的影响. tcp相关延时主要包括: 1.tcp连接时建立握手: 2.tcp慢启动拥塞控制: 3.数据聚集的Nagle算法: 4.用于捎带确认的tcp延迟确认算法: 5.TIME_WAIT时延和端口耗尽. 对上面的延时影响,相应的优化方法有: 1.http使用“持久化连接”,http 1.0中使用connection:keep-alive, http 1.1默认使用持久化连接: 2.调整或禁止延迟确认算法(

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

#include "lrs.h" vuser_init(){ char *ip; int handler; //编写获取LR分配的Vuser IP函数,将IP保存在ip变量中. ip=lr_get_vuser_ip(); if(ip) lr_vuser_status_message("the ip address is %s:",ip); else lr_vuser_status_message("IP spooler disabled"); /