您的位置:首页 > 理论基础 > 计算机网络

一个简单的HTTP并发测试程序

2011-09-21 14:16 489 查看
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

#define MAX_THREAD 500

static unsigned long long run_time = 0;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

struct HttpStatistics	//计时
{
unsigned long long requestTime;
unsigned long long responseTime;
};

struct HttpGetParam	//参数
{
char *url;
struct HttpStatistics httpStatistics;
};

unsigned long long GetCurrentNanoseconds()//当前时间
{
struct timespec tvTime;
clock_gettime(CLOCK_REALTIME, &tvTime);
return (unsigned long long)tvTime.tv_sec * 1000000000ULL + (unsigned long long)tvTime.tv_nsec;
}

static size_t write_data(void *ptr, size_t size, size_t nmemb, void *param)
{
return size * nmemb;
}

static size_t head_data(void *ptr, size_t size, size_t nmemb, void *param)
{
struct HttpGetParam *phttpGetParam = (struct HttpGetParam *)param;
unsigned long long currentTime = 0;
unsigned long long usedTime = 0;

if ( phttpGetParam->httpStatistics.responseTime == 0)//只记录第一次收到报文时候的内容
{
currentTime = GetCurrentNanoseconds();
phttpGetParam->httpStatistics.responseTime = currentTime;
usedTime = currentTime - phttpGetParam->httpStatistics.requestTime;
//printf("Time is:%llu\n", usedTime/1000000);
//printf("%s\n", (char*)ptr);
pthread_mutex_lock(&mutex);
run_time++;
pthread_mutex_unlock(&mutex);
}
return size * nmemb;
}

//每个线程的处理
void * http_get(void *param)
{
struct HttpGetParam *phttpGetParam = (struct HttpGetParam *)param;

CURL *curl;//定义CURL类型的指针
CURLcode res; //定义CURLcode类型的变量

//pthread_detach(pthread_self());
curl = curl_easy_init();//初始化一个CURL类型的指针

//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);//这里打开libcurl打印所有调试信息

//curl_easy_setopt(curl, CURLOPT_WRITEDATA, phttpGetParam);
curl_easy_setopt(curl, CURLOPT_HEADERDATA, phttpGetParam);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); //加上这一句就不会把HTTP Body打出来了。。。
//curl_easy_setopt(curl, CURLOPT_NOBODY, 1);//CURLOPT_NOBODY只下报文头,不包括数据.但是这里默认是head命令,这里注释掉,则是GET命令
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, head_data);

//设置curl选项. 其中CURLOPT_URL是让用户指定url. argv[1]中存放的命令行传进来的网址
curl_easy_setopt(curl, CURLOPT_URL, phttpGetParam->url);

while( 1 )
{
phttpGetParam->httpStatistics.requestTime = GetCurrentNanoseconds();
phttpGetParam->httpStatistics.responseTime = 0;
//调用curl_easy_perform 执行我们的设置.并进行相关的操作. 在这里只在屏幕上显示出来.
res = curl_easy_perform(curl);//这里可以用循环实现每个线程内部多次处理
//printf("res=%d\n", res);
}
//清除curl操作.
curl_easy_cleanup(curl);
return NULL;
}

int main(int argc, char *argv[])
{
CURLcode res; //定义CURLcode类型的变量
pthread_t threads[MAX_THREAD];//PID
int i, ret;
struct HttpGetParam httpGetParams[MAX_THREAD];
pthread_attr_t thread_attr;
size_t stack_size;

if (argc !=2)
{
printf("Usage : %s <url>;\n", argv[0]);
exit(1);
}

res = curl_global_init(CURL_GLOBAL_ALL);
if (res != CURLE_OK)
{
printf( "Failed to global init default [%d]\n", res );
return -1;
}

memset(threads, 0, sizeof(threads));
memset(httpGetParams, 0, sizeof(httpGetParams));

for ( i = 0; i < MAX_THREAD; i++)
{
httpGetParams[i].url = argv[1];
}

printf("PTHREAD_STACK_MIN=%d\n", PTHREAD_STACK_MIN);
pthread_attr_init(&thread_attr);
pthread_attr_getstacksize(&thread_attr, &stack_size);
printf("Default stack size is %u; minimum is %u\n",
stack_size, PTHREAD_STACK_MIN);
pthread_attr_setstacksize(&thread_attr, 1024 * 1024); //设置线程栈大小,这里设置成了1M,这个可能需要根据情况调,最小不能小于PTHREAD_STACK_MIN,如果太小有可能出现栈溢出
pthread_attr_getstacksize(&thread_attr, &stack_size);
printf("New stack size is %u; minimum is %u\n",
stack_size, PTHREAD_STACK_MIN);
for ( i = 0; i < MAX_THREAD; i++)
{
//创建线程,threads线程ID
//ret = pthread_create(&threads[i], NULL, http_get, (void *)&httpGetParams[i]);
ret = pthread_create(&threads[i], &thread_attr, http_get, (void *)&httpGetParams[i]);
if (0 != ret)
{
perror("pthread_create failed!!! The reason is:");
}

if ( (i + 1) % 5 == 0)
{
sleep(10);
printf("Thread num:%d,\tAVG request per second:%llu,\tAVG response time:%f\n", i + 1, run_time/10, 10.0/run_time);
pthread_mutex_lock(&mutex);
run_time = 0;
pthread_mutex_unlock(&mutex);
}
}
pthread_attr_destroy(&thread_attr);

//sleep(30);
//等待线程退出
for ( i = 0; i < MAX_THREAD; i++)
{
//判断pthread_t是否有效,解决了段错误问题。
if (threads[i] != 0)
{
pthread_cancel(threads[i]);
pthread_join(threads[i], NULL);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: