您的位置:首页 > 其它

之前写的SSL的性能测试程序

2013-03-14 11:13 218 查看

client.c

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <sys/mman.h>

#define MAXBUF 1024
#define MAX_THREADS 100
#define SUBTHREADNUM 2

int pkgSize = 1024;
int threads = 10;
int times = 10;
int mode = 0;            //0-handshake 1-throughput 2-full
int sslversion = 1;        //0-SSLv2 1-SSLv3 2-SSLv23 3-TLSv1 4-TLSv1_1 5-TLSv1_2
char *ip = "127.0.0.1";
int port = 8701;
char *cipher = "AES128-SHA";
int debug = 0;
int showTitle = 1;

struct cpuinfo
{
char name[20];
unsigned int user;
unsigned int nice;
unsigned int system;
unsigned int idle;
unsigned int iowait;
unsigned int irq;
unsigned int softirq;
unsigned int stealstolen;
unsigned int guest;
};

void throughputTest();
void handshakeTest();
void fullTest();
void apacheTest();
void getCpuInfo (struct cpuinfo *cpu);
void calCpuUseRatio (struct cpuinfo *old, struct cpuinfo *new);
int getCpuTotalUseRatio();

struct shm_layout
{
u_int64_t count[MAX_THREADS];
u_int64_t t1[MAX_THREADS];
u_int64_t t2[MAX_THREADS];
int ready[MAX_THREADS];
int done[MAX_THREADS];
volatile int start;
volatile int exit;
volatile int stop;
};

struct subthread_layout
{
u_int64_t starttime[SUBTHREADNUM];
u_int64_t endtime[SUBTHREADNUM];
u_int64_t count[SUBTHREADNUM];
};

struct shm_layout *shared_region = NULL;
struct subthread_layout subthread_region;
u_int64_t total_count = 0ull;
int thread_id = 0;
u_int64_t min_t1 = 0ull, max_t2 = 0ull;
u_int64_t total_throughput = 0;
int pid[100];
struct sockaddr_in dest;
char *buffer;
SSL_CTX *ctx;

void usage()
{
printf("Usage: Client \n\
-a   IP Addr (127.0.0.1) \n\
-c   Cipher (AES128-SHA) \n\
-p   Port (8701)\n\
-s   Package Size (1024)\n\
-t   Times (10)\n\
-l   Threads (10)\n\
-m   Mode (0-handshake 1-throughput 2-full 3-apachessl default 0)\n\
-v   SSLVersion (0-SSLv2 1-SSLv3 2-SSLv23 3-TLSv1 4-TLSv1_1 5-TLSv1_2 default 1)\n\
-d   Debug Info\n\
-h   Help\n");
exit(-1);
}

void min_max_times(int count, u_int64_t *t1, u_int64_t *t2, u_int64_t *min_t1, u_int64_t *max_t2)
{
int i = 0;

*min_t1 = t1[0];
*max_t2 = t2[0];
for(i = 1; i < count; i++)
{
if(t1[i] < *min_t1)
*min_t1 = t1[i];
if(t2[i] > *max_t2)
*max_t2 = t2[i];
}
}

u_int64_t apiTimeUs()
{
struct timeval m_real1;
u_int64_t temp;

gettimeofday (&m_real1, 0);
temp = m_real1.tv_sec;
temp = (temp * 1000000) + m_real1.tv_usec;

return temp;
}

char* randomStr()
{
char *tmp = malloc(pkgSize * sizeof(char) + 1);
int i;
srand(time(NULL));
for(i = 0; i < pkgSize; i++)
{
do
{
tmp[i] = rand() % 128;
}while(!isprint(tmp[i]));
}
tmp[i] = '\0';
return tmp;
}

int main(int argc, char **argv)
{
char options[] = "a:c:m:t:s:p:v:l:hde";
int opt;
while((opt = getopt(argc, argv, options)) != -1)
{
switch(opt)
{
case 't':
times = atoi(optarg);
//printf("times:%d\n", times);
break;
case 'c':
cipher = optarg;
break;
case 's':
pkgSize = atoi(optarg);
//printf("pkgSize:%d\n", pkgSize);
break;
case 'l':
threads = atoi(optarg);
//printf("threads:%d\n", threads);
break;
case 'p':
port = atoi(optarg);
//printf("port:%d\n", port);
break;
case 'a':
ip = optarg;
//printf("IP:%s\n", ip);
break;
case 'm':
mode = atoi(optarg);
//printf("type:%d\n", mode);
break;
case 'v':
sslversion = atoi(optarg);
//printf("type:%d\n", sslversion);
break;
case 'd':
debug = 1;
break;
case 'e':
showTitle = 0;
break;
case 'h':
default:
usage();
break;
}
}
if(showTitle)
{
char *title[4] = {"Handshake Test", "Throughput Test", "HS And TP Test", "Apache SSL Test"};
char *version[6] = {"SSLv2", "SSLv3", "SSLv23", "TLSv1", "TLSv1_1", "TLSv1_2"};
char tmpStr[200] = {0};
sprintf(tmpStr, "%s%s%s", "------------------------------------------------ ", title[mode], " ------------------------------------------------");
printf("%s\n", tmpStr);
printf("Server IP        Server Port        Thread Number        Times        Package Size        Cipher        Version\n");
printf("%-20s %-20d %-15d %-16d %-12d %-16s %s\n", ip, port, threads, times, pkgSize, cipher, version[sslversion]);
}
int status[100];

shared_region = mmap(NULL, sizeof(struct shm_layout), PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
if(shared_region == MAP_FAILED)
{
printf("\n ERROR mapping \n");
exit(1);
}
memset(shared_region, 0, sizeof(struct shm_layout));
//SSL 库初始化,参看 ssl-server.c 代码
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(SSLv3_client_method());
if (ctx == NULL)
{
ERR_print_errors_fp(stdout);
exit(1);
}

//初始化服务器端(对方)的地址和端口信息
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(port);
if (inet_aton(ip, (struct in_addr *) &dest.sin_addr.s_addr) == 0)
{
perror(argv[1]);
exit(errno);
}
//printf("address created\n");

if(!SSL_CTX_set_cipher_list(ctx, cipher))
{
SSL_CTX_free(ctx);
exit(1);
}
buffer = randomStr();
if(debug)
{
printf("buffer:%s\n", buffer);
}
int i;
for(i = 0; i < threads; i++)
{
int kid = fork();
if(kid < 0)
{
printf("Fork failed, Failed to create a new thread\n");
}
if(kid == 0)
{
thread_id = i;

if(mode == 0)
{
handshakeTest();
}
else if(mode == 1)
{
throughputTest();
}
else if(mode == 2)
{
fullTest();
}
else if(mode == 3)
{
apacheTest();
}

shared_region->done[thread_id] = 1;
sync();
/* loop till all other threads are ready */
while ((volatile int)shared_region->exit == 0)
{
sleep(1);
}
exit(0);
}
else
{
pid[i] = kid;
}
}

for(i = 0;i < threads; i++)
{
while((volatile int)shared_region->ready[i] == 0)
{
usleep(10);
}
}
shared_region->start = 1;
u_int64_t starttime, endtime;
starttime = apiTimeUs();
sync();
sleep(2);
endtime = apiTimeUs();
u_int64_t timeuse = endtime - starttime;
while(timeuse < times * 1000000)
{
usleep(times * 1000000 - timeuse);
endtime = apiTimeUs();
timeuse = endtime - starttime;
continue;
}
shared_region->stop = 1;
for(i = 0;i < threads; i++)
{
while((volatile int)shared_region->done[i] == 0)
{
usleep(10);
}
}
shared_region->exit = 1;
sync();

for(i = 0; i < threads; i++)
{
waitpid(pid[i], &status[i], 0);
}

for(i = 0;i < threads; i++)
{
total_count += shared_region->count[i];
}

min_max_times(threads, shared_region->t1, shared_region->t2, &min_t1, &max_t2);
total_throughput = (u_int64_t)((total_count) * 1000000) / (max_t2 - min_t1);
if(showTitle)
{
printf("                        --------------------------- Result ---------------------------\n");
}
if(mode == 1)
{
total_throughput = total_throughput * pkgSize / 1024 / 1024 * 8;
if(showTitle)
{
printf("                        Package Size(Bytes)        Operations        Throughtput(Mbps)\n");
printf("                              %-22d %-20llu %llu\n", pkgSize, (unsigned long long)total_count, (unsigned long long)total_throughput);
}
else
{
printf("                     %-22d %-20llu %llu\n", pkgSize, (unsigned long long)total_count, (unsigned long long)total_throughput);
}
}
else if(mode == 0)
{
if(showTitle)
{
printf("                        Package Size(Bytes)        Operations         Operations/Sec\n");
printf("                              %-23d %-20llu %llu\n", pkgSize, (unsigned long long)total_count, (unsigned long long)total_throughput);
}
else
{
printf("                     %-23d %-20llu %llu\n", pkgSize, (unsigned long long)total_count, (unsigned long long)total_throughput);
}
}
else if(mode == 2)
{
if(showTitle)
{
printf("                        Module Size (Bytes)        Operations         Operations/Sec\n");
printf("                              %-23d %-20llu %llu\n", 1024, (unsigned long long)total_count, (unsigned long long)total_throughput);
}
else
{
printf("                     %-23d %-20llu %llu\n", 1024, (unsigned long long)total_count, (unsigned long long)total_throughput);
}
}
else if(mode == 3)
{
if(showTitle)
{
printf("                        Module Size (Bytes)        Operations         Operations/Sec\n");
printf("                              %-23d %-20llu %llu\n", 1024, (unsigned long long)total_count, (unsigned long long)total_throughput);
}
else
{
printf("                     %-23d %-20llu %llu\n", 1024, (unsigned long long)total_count, (unsigned long long)total_throughput);
}
}
//printf ("%-8d          %-8u         %-8%llu           %-dd8llu\n", buflen, total_throughput, total_count, max_t2-min_t1);
munmap(shared_region, sizeof(struct shm_layout));
fflush(stdout);
sleep(2);
return 0;
}

void handshakeTest()
{
int sockfd, len;
SSL *ssl;
shared_region->ready[thread_id] = 1;
sync();
while ((volatile int)shared_region->start == 0);

u_int64_t count = 0;
u_int64_t starttime, endtime;
starttime = apiTimeUs();
while ((volatile int)shared_region->stop == 0)
{
//创建一个 socket 用于 tcp 通信
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Socket");
break;
}
//printf("socket created!\n");

//连接服务器
if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0)
{
perror("Connect ");
close(sockfd);
break;
}
//printf("server connected!\n");

//基于 ctx 产生一个新的 SSL
ssl = SSL_new(ctx);
if(count % 2 == 0)
{
SSL_free(ssl);
ssl = SSL_new(ctx);
}

SSL_set_fd(ssl, sockfd);
//建立 SSL 连接
if (SSL_connect(ssl) == -1)
{
perror("SSL connect");
SSL_free(ssl);
close(sockfd);
break;
}
else
{
count++;
if(debug)
{
if(count == 1)
{
printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
}
}
}
// 关闭连接
//SSL_shutdown(ssl);
SSL_free(ssl);
close(sockfd);
}
endtime = apiTimeUs();
SSL_CTX_free(ctx);

shared_region->count[thread_id] = count;
shared_region->t1[thread_id] = starttime;
shared_region->t2[thread_id] = endtime;
sync();
}

void *createThread(void *arg)
{
int sockfd, len;
SSL *ssl;
//创建一个 socket 用于 tcp 通信
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Socket");
SSL_CTX_free(ctx);
return;
}
//printf("socket created!\n");

//连接服务器
if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0)
{
perror("Connect ");
close(sockfd);
SSL_CTX_free(ctx);
return;
}
//printf("server connected!\n");
//基于 ctx 产生一个新的 SSL
ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockfd);
//建立 SSL 连接
if (SSL_connect(ssl) == -1)
{
//ERR_print_errors_fp(stderr);
perror("SSL connect");
SSL_free(ssl);
close(sockfd);
SSL_CTX_free(ctx);
return;
}
else
{
if(debug)
{
printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
}
}

u_int64_t count = 0;
int threadNum = (int)(*((int*)arg));
subthread_region.starttime[threadNum] = apiTimeUs();
while ((volatile int)shared_region->stop == 0)
{
len = SSL_write(ssl, buffer, strlen(buffer));
if (len < 0)
{
printf("消息发送失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
break;
}
else
{
count++;
//printf("消息'%s'发送成功,共发送了%d个字节!\n", buffer, len);
}
}
subthread_region.endtime[threadNum] = apiTimeUs();
subthread_region.count[threadNum] = count;
// 关闭连接
SSL_shutdown(ssl);
SSL_free(ssl);
close(sockfd);
return NULL;
}

void throughputTest()
{
shared_region->ready[thread_id] = 1;
sync();
while ((volatile int)shared_region->start == 0);
/*
pthread_t thread[SUBTHREADNUM];
int i;
for(i = 0; i < SUBTHREADNUM; i++)
{
if(pthread_create(&thread[i], NULL, createThread, (void *)&i) != 0)//创建子线程
{
perror("pthread_create");
break;
}
}

for(i = 0; i < SUBTHREADNUM; i++)
{
pthread_join(thread[i], NULL);
}
*/
int sockfd, len;
SSL *ssl;
//创建一个 socket 用于 tcp 通信
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Socket");
SSL_CTX_free(ctx);
return;
}
//printf("socket created!\n");

//连接服务器
if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0)
{
perror("Connect ");
close(sockfd);
SSL_CTX_free(ctx);
return;
}
//printf("server connected!\n");
//基于 ctx 产生一个新的 SSL
ssl = SSL_new(ctx);
if(thread_id >= threads / 2)
{
SSL_free(ssl);
ssl = SSL_new(ctx);
}
SSL_set_fd(ssl, sockfd);
//建立 SSL 连接
if (SSL_connect(ssl) == -1)
{
//ERR_print_errors_fp(stderr);
perror("SSL connect");
SSL_free(ssl);
close(sockfd);
SSL_CTX_free(ctx);
return;
}
else
{
if(debug)
{
printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
}
}

u_int64_t count = 0;
u_int64_t starttime, endtime;
starttime = apiTimeUs();
while ((volatile int)shared_region->stop == 0)
{
len = SSL_write(ssl, buffer, strlen(buffer));
if (len < 0)
{
printf("消息发送失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
break;
}
else
{
count++;
//printf("消息'%s'发送成功,共发送了%d个字节!\n", buffer, len);
}
}
endtime = apiTimeUs();
// 关闭连接
//SSL_shutdown(ssl);
SSL_free(ssl);
close(sockfd);
SSL_CTX_free(ctx);
//业务处理结束
/*
u_int64_t starttime, endtime;
min_max_times(SUBTHREADNUM, subthread_region.starttime, subthread_region.endtime, &starttime, &endtime);
u_int64_t count = 0;
for(i = 0; i < SUBTHREADNUM; i++)
{
count += subthread_region.count[i];
}
*/
shared_region->count[thread_id] = count;
shared_region->t1[thread_id] = starttime;
shared_region->t2[thread_id] = endtime;
sync();
}

void fullTest()
{
int sockfd, len;
SSL *ssl;
shared_region->ready[thread_id] = 1;
sync();
while ((volatile int)shared_region->start == 0);

u_int64_t count = 0;
u_int64_t starttime, endtime;
starttime = apiTimeUs();
while ((volatile int)shared_region->stop == 0)
{
//创建一个 socket 用于 tcp 通信
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Socket");
break;
}
//printf("socket created!\n");

//连接服务器
if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0)
{
perror("Connect ");
close(sockfd);
break;
}
//printf("server connected!\n");

//基于 ctx 产生一个新的 SSL
ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockfd);
//建立 SSL 连接
if (SSL_connect(ssl) == -1)
{
perror("SSL connect");
SSL_free(ssl);
close(sockfd);
break;
}
else
{
len = SSL_write(ssl, buffer, strlen(buffer));
if (len < 0)
{
printf("消息发送失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
SSL_free(ssl);
close(sockfd);
break;
}
else
{
count++;
//printf("消息'%s'发送成功,共发送了%d个字节!\n", buffer, len);
}
if(debug)
{
if(count == 1)
{
printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
}
}
}
// 关闭连接
//SSL_shutdown(ssl);
SSL_free(ssl);
close(sockfd);
}
endtime = apiTimeUs();
SSL_CTX_free(ctx);

shared_region->count[thread_id] = count;
shared_region->t1[thread_id] = starttime;
shared_region->t2[thread_id] = endtime;
sync();
}

void apacheTest()
{
int sockfd, len;
SSL *ssl;
shared_region->ready[thread_id] = 1;
sync();
while ((volatile int)shared_region->start == 0);

u_int64_t count = 0;
u_int64_t starttime, endtime;
starttime = apiTimeUs();
char readBuff[MAXBUF] = {0};
char writeData[200] = {0};
sprintf(writeData, "%s%s%s", "GET /index.html HTTP/1.1\r\nHost: ", ip, "\r\nConnection: Close\r\n");
while ((volatile int)shared_region->stop == 0)
{
//创建一个 socket 用于 tcp 通信
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Socket");
break;
}
//printf("socket created!\n");

//连接服务器
if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0)
{
perror("Connect ");
close(sockfd);
break;
}
//printf("server connected!\n");

//基于 ctx 产生一个新的 SSL
ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockfd);
//建立 SSL 连接
if (SSL_connect(ssl) == -1)
{
perror("SSL connect");
SSL_free(ssl);
close(sockfd);
break;
}
else
{
len = SSL_write(ssl, writeData, strlen(writeData));
if (len < 0)
{
printf("消息发送失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
SSL_free(ssl);
close(sockfd);
break;
}
else
{
count++;
printf("消息'%s'发送成功,共发送了%d个字节!\n", readBuff, len);
}
memset(readBuff, 0 , MAXBUF);
len = SSL_read(ssl, readBuff, MAXBUF);
if(len < 0)
{
printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
SSL_free(ssl);
close(sockfd);
break;
}
if(debug)
{
if(count == 1)
{
printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
printf("The Apache data: %s\n", readBuff);
}
}
}
// 关闭连接
//SSL_shutdown(ssl);
SSL_free(ssl);
close(sockfd);
}
endtime = apiTimeUs();
SSL_CTX_free(ctx);

shared_region->count[thread_id] = count;
shared_region->t1[thread_id] = starttime;
shared_region->t2[thread_id] = endtime;
sync();
}

/**
* 获取总的CPU利用率
*/
int getCpuTotalUseRatio()
{
struct cpuinfo oldinfo;
struct cpuinfo newinfo;
getCpuInfo(&oldinfo);
sleep(1);
getCpuInfo(&newinfo);
calCpuUseRatio(&oldinfo, &newinfo);
}

/**
* 计算CPU利用率
*/
void calCpuUseRatio (struct cpuinfo *old, struct cpuinfo *new)
{
double oldTotal, newTotal, total, idle, user, system, softirq, irq;
float totalRatio, userRatio, systemRatio, softirqRatio, irqRatio;
oldTotal = (double)(old->user + old->nice + old->system + old->idle + old->iowait +
old->irq + old->softirq + old->stealstolen + old->guest);
newTotal = (double)(new->user + new->nice + new->system + new->idle + new->iowait +
new->irq + new->softirq + new->stealstolen + new->guest);

total = newTotal - oldTotal;
idle  = new->idle - old->idle;
user = new->user - old->user;
system = new->system - old->system;
softirq = new->softirq - old->softirq;
irq = new->irq - old->irq;

//CPU利用率
totalRatio = (total - idle) / total;
//用户空间CPU利用率
userRatio = user / total;
//内核空间CPU利用率
systemRatio = system / total;
//软中断CPU利用率
softirqRatio = softirq / total;
//硬中断CPU利用率
irqRatio = irq / total;
//printf("total:%f, idle:%f, new->idle:%u, old->idle:%u\n", total, idle, new->idle, old->idle);
printf("总的CPU利用率为:%f(%f + %f + %f + %f)\n", totalRatio, userRatio, systemRatio, softirqRatio, irqRatio);
}

/**
* 获取当前CPU信息
*/
void getCpuInfo (struct cpuinfo *cpu)
{
FILE *fd;
char buff[1024];
fd = fopen ("/proc/stat", "r");
fgets (buff, sizeof(buff), fd);
sscanf (buff, "%s  %u %u %u %u %u %u %u %u %u", &cpu->name, &cpu->user, &cpu->nice, &cpu->system,
&cpu->idle,&cpu->iowait, &cpu->irq, &cpu->softirq, &cpu->stealstolen, &cpu->guest);
printf ("%s %u %u %u %u %u %u %u %u %u\n", cpu->name, cpu->user, cpu->nice, cpu->system,
cpu->idle, cpu->iowait, cpu->irq, cpu->softirq, cpu->stealstolen, cpu->guest);
fclose(fd);
}

server.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <sys/mman.h>

#define SUBTHREADNUM 2
#define MAX_THREADS 100

int pkgSize = 1024;
int threads = 10;
int mode = 0;    //0-handshake 1-throughput
int port = 8701;

void handshakeTest();
void throughputTest();

SSL_CTX *ctx;
char *buffer;
int sockfd;
int debug = 0;
int thread_id = 0;
int pid[100];
int showTitle = 1;
int times = 10;

struct cpuinfo
{
char name[20];
unsigned int user;
unsigned int nice;
unsigned int system;
unsigned int idle;
unsigned int iowait;
unsigned int irq;
unsigned int softirq;
unsigned int stealstolen;
unsigned int guest;
};

void getCpuInfo (struct cpuinfo *cpu);
void calCpuUseRatio (struct cpuinfo *old, struct cpuinfo *new);
int getCpuTotalUseRatio();

struct shm_layout
{
int ready[MAX_THREADS];
int done[MAX_THREADS];
int failCount[MAX_THREADS];
};

struct shm_layout *shared_region = NULL;
void usage()
{
printf("Usage: Client \n\
-p   Port (8701)\n\
-s   Package Size (1024)\n\
-l   Threads (10)\n\
-m   Type (0-handshake 1-throughput default 0)\n\
-d   Debug Info\n\
-t   Time\n\
-h   Help\n");
exit(-1);
}

int main(int argc, char **argv)
{
char options[] = "a:s:p:m:l:t:hde";
int opt;
while((opt = getopt(argc, argv, options)) != -1)
{
switch(opt)
{
case 's':
pkgSize = atoi(optarg);
//printf("pkgSize:%d\n", pkgSize);
break;
case 'l':
threads = atoi(optarg);
//printf("threads:%d\n", threads);
break;
case 'p':
port = atoi(optarg);
//printf("port:%d\n", port);
break;
case 'm':
mode = atoi(optarg);
//printf("type:%d\n", mode);
break;
case 'd':
debug = 1;
break;
case 't':
times = atoi(optarg);
case 'e':
showTitle = 0;
break;
case 'h':
default:
usage();
break;
}
}
if(showTitle)
{
if(mode == 0)
{
printf("------------------- Handshake Test -------------------\n");
}
else if(mode == 1)
{
printf("------------------- Throughput Test -------------------\n");
}
printf("Server Port        Thread Number        Package Size\n");
}
printf("    %-20d %-20d %-18d\n", port, threads, pkgSize);

shared_region = mmap(NULL, sizeof(struct shm_layout), PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
if(shared_region == MAP_FAILED)
{
printf("\n ERROR mapping \n");
exit(1);
}
memset(shared_region, 0, sizeof(struct shm_layout));

struct sockaddr_in my_addr;
unsigned int lisnum;

lisnum = 20;

buffer = malloc(pkgSize + 1);
memset(buffer, 0 , pkgSize + 1);

//SSL 库初始化
SSL_library_init();
//载入所有 SSL 算法
OpenSSL_add_all_algorithms();
//载入所有 SSL 错误消息
SSL_load_error_strings();
//以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL Content Text
ctx = SSL_CTX_new(SSLv3_server_method());
//也可以用 SSLv2_server_method() 或 SSLv3_server_method() 单独表示 V2 或 V3标准
if (ctx == NULL)
{
printf("SSLContext failed!\n");
exit(1);
}
//载入用户的数字证书, 此证书用来发送给客户端。 证书里包含有公钥
if (SSL_CTX_use_certificate_file(ctx, "cacert.pem", SSL_FILETYPE_PEM) <= 0)
{
printf("Certificate load failed!\n");
exit(1);
}
//载入用户私钥
if (SSL_CTX_use_PrivateKey_file(ctx, "privkey.pem", SSL_FILETYPE_PEM) <= 0)
{
printf("PrivateKey load failed!\n");
exit(1);
}
//检查用户私钥是否正确
if (!SSL_CTX_check_private_key(ctx))
{
printf("PrivateKey check failed!\n");
exit(1);
}

//开启一个 socket 监听
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}
else
{
if(debug)
{
printf("socket created\n");
}
}

bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons(port);
my_addr.sin_addr.s_addr = INADDR_ANY;

if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1)
{
perror("bind");
exit(1);
}
else
{
if(debug)
{
printf("binded\n");
}
}

if (listen(sockfd, lisnum) == -1)
{
perror("listen");
exit(1);
}
else
{
if(debug)
{
printf("begin listen\n");
}
}

int i;
for(i = 0; i < threads; i++)
{
int kid = fork();
if(kid < 0)
{
printf("Fork failed, Failed to create a new thread\n");
}
if(kid == 0)
{
thread_id = i;
if(mode == 0)
{
handshakeTest();
}
else if(mode == 1)
{
throughputTest();
}
shared_region->done[thread_id] = 1;
exit(0);
}
else
{
pid[i] = kid;
}
}

for(i = 0;i < threads; i++)
{
while((volatile int)shared_region->ready[i] == 0)
{
usleep(10);
}
}

getCpuTotalUseRatio();

for(i = 0;i < threads; i++)
{
while((volatile int)shared_region->done[i] == 0)
{
usleep(1000);
}
}

int total_fail_count = 0;
for(i = 0;i < threads; i++)
{
total_fail_count += shared_region->failCount[i];
}
if(total_fail_count != threads)
{
printf("-------------------------------- Warning: failed count is %d --------------------------------\n", total_fail_count);
}
// 关闭监听的 socket
close(sockfd);
}

void handshakeTest()
{
SSL *ssl;
int new_fd;
int i = 0;
int count = 0;
while(1)
{
//等待客户端连上来
if ((new_fd = accept(sockfd, NULL, NULL)) == -1)
{
if(count == 0)
{
shared_region->ready[thread_id] = 1;
sync();
}
perror("accept");
exit(errno);
}
else
{
//printf("Accepted success!\n");
}
//基于 ctx 产生一个新的 SSL
ssl = SSL_new(ctx);
if(count % 2 == 0)
{
SSL_free(ssl);
ssl = SSL_new(ctx);
}
//将连接用户的 socket 加入到 SSL
SSL_set_fd(ssl, new_fd);
//建立 SSL 连接
if (SSL_accept(ssl) == -1)
{
perror("accept");
SSL_free(ssl);
close(new_fd);
break;
}
count++;
//SSL_shutdown(ssl);
//释放 SSL
SSL_shutdown(ssl);
SSL_free(ssl);
//关闭 socket
close(new_fd);
}
SSL_CTX_free(ctx);
}

void *createThread(void *arg)
{
SSL *ssl;
int new_fd;
int len;
/* 等待客户端连上来 */
if ((new_fd = accept(sockfd, NULL, NULL)) == -1)
{
perror("accept");
exit(errno);
}
else
{
if(debug)
{
printf("Accepted success!\n");
}
}

//基于 ctx 产生一个新的 SSL
ssl = SSL_new(ctx);
//将连接用户的 socket 加入到 SSL
SSL_set_fd(ssl, new_fd);
//建立 SSL 连接
if (SSL_accept(ssl) == -1)
{
perror("accept");
close(new_fd);
exit(0);
}
int i = 0;
while(1)
{
bzero(buffer, pkgSize + 1);
//接收客户端的消息
len = SSL_read(ssl, buffer, pkgSize);
if (len > 0)
{
if(debug)
{
i++;
if(i == 1)
{
printf("接收消息成功:'%s',共%d个字节的数据\n", buffer, len);
}
}
}
else
{
printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
break;
}
}
//SSL_shutdown(ssl);
//释放 SSL
SSL_free(ssl);
//关闭 socket
close(new_fd);
return NULL;
}

void throughputTest()
{
/*
pthread_t thread[SUBTHREADNUM];
int i;
for(i = 0; i < SUBTHREADNUM; i++)
{
if(pthread_create(&thread[i], NULL, createThread, NULL) != 0)//创建子线程
{
perror("pthread_create");
break;
}
}

for(i = 0; i < SUBTHREADNUM; i++)
{
pthread_join(thread[i], NULL);
}
*/
SSL *ssl;
int new_fd;
int len;
/* 等待客户端连上来 */
if ((new_fd = accept(sockfd, NULL, NULL)) == -1)
{
perror("accept");
exit(errno);
}
else
{
if(debug)
{
printf("Accepted success!\n");
}
}
shared_region->ready[thread_id] = 1;
sync();
//基于 ctx 产生一个新的 SSL
ssl = SSL_new(ctx);
if(thread_id >= threads / 2)
{
SSL_free(ssl);
ssl = SSL_new(ctx);
}
//将连接用户的 socket 加入到 SSL
SSL_set_fd(ssl, new_fd);
//建立 SSL 连接
if (SSL_accept(ssl) == -1)
{
perror("accept");
close(new_fd);
exit(0);
}
int i = 0;
while(1)
{
bzero(buffer, pkgSize + 1);
//接收客户端的消息
len = SSL_read(ssl, buffer, pkgSize);
if (len > 0)
{
if(debug)
{
i++;
if(i == 1)
{
printf("接收消息成功:'%s',共%d个字节的数据\n", buffer, len);
}
}
}
else
{
if(debug)
{
printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno));
}
shared_region->failCount[thread_id]++;
break;
}
}
sync();
//SSL_shutdown(ssl);
//释放 SSL
SSL_free(ssl);
//关闭 socket
close(new_fd);
SSL_CTX_free(ctx);
}

/**
* 获取总的CPU利用率
*/
int getCpuTotalUseRatio()
{
struct cpuinfo oldinfo;
struct cpuinfo newinfo;
getCpuInfo(&oldinfo);
sleep(times - 1);
getCpuInfo(&newinfo);
calCpuUseRatio(&oldinfo, &newinfo);
}

/**
* 计算CPU利用率
*/
void calCpuUseRatio (struct cpuinfo *old, struct cpuinfo *new)
{
double oldTotal, newTotal, total, idle, user, system, softirq, irq;
float totalRatio, userRatio, systemRatio, softirqRatio, irqRatio;
oldTotal = (double)(old->user + old->nice + old->system + old->idle + old->iowait +
old->irq + old->softirq + old->stealstolen + old->guest);
newTotal = (double)(new->user + new->nice + new->system + new->idle + new->iowait +
new->irq + new->softirq + new->stealstolen + new->guest);

total = newTotal - oldTotal;
idle  = new->idle - old->idle;
user = new->user - old->user;
system = new->system - old->system;
softirq = new->softirq - old->softirq;
irq = new->irq - old->irq;

//CPU利用率
totalRatio = (total - idle) / total;
//用户空间CPU利用率
userRatio = user / total;
//内核空间CPU利用率
systemRatio = system / total;
//软中断CPU利用率
softirqRatio = softirq / total;
//硬中断CPU利用率
irqRatio = irq / total;
//printf("total:%f, idle:%f, new->idle:%u, old->idle:%u\n", total, idle, new->idle, old->idle);
printf("%f(%f + %f + %f + %f)\n", totalRatio, userRatio, systemRatio, softirqRatio, irqRatio);
}

/**
* 获取当前CPU信息
*/
void getCpuInfo (struct cpuinfo *cpu)
{
FILE *fd;
char buff[1024];
fd = fopen ("/proc/stat", "r");
fgets (buff, sizeof(buff), fd);
sscanf (buff, "%s  %u %u %u %u %u %u %u %u %u", &cpu->name, &cpu->user, &cpu->nice, &cpu->system,
&cpu->idle,&cpu->iowait, &cpu->irq, &cpu->softirq, &cpu->stealstolen, &cpu->guest);
//printf ("%s %u %u %u %u %u %u %u %u %u\n", cpu->name, cpu->user, cpu->nice, cpu->system,
//cpu->idle, cpu->iowait, cpu->irq, cpu->softirq, cpu->stealstolen, cpu->guest);
fclose(fd);
}

Makefile

CIPHER    = AES128-SHA      #AES128-SHA AES256-SHA RC4-SHA RC4-MD5
PKT_SIZES = 256 512 1024 1500 2048
RSA       = RSA_CRT RSA_NOCRT MODEXP
HANDSHAKE = RSASERVERFULL
NUM_THREADS      = 40       #MAX 100
NUM_THREADSHS    = 60       #MAX 100
NB_TEST_DURATION = 5
HANDSHAKEIP      = 168.1.1.10
THROUGHPUTIP     = 169.1.1.10
TIME             = 10
LOOP             = 1 2 3 4 5 6
PORT             = 8701

CFLAGS = -I/usr/local/ssl/include -L/usr/local/ssl/lib -lssl -lcrypto -ldl
CC = gcc
OBJS_SERVER = server.o
OBJS_CLIENT = client.o

all:server client

server: $(OBJS_SERVER)
$(CC) -o $@ $^ ${CFLAGS}
client: $(OBJS_CLIENT)
$(CC) -o $@ $^ ${CFLAGS}

handshake_client:
for pktsize in ${PKT_SIZES}; do \
./client -a ${THROUGHPUTIP} -l ${NUM_THREADSHS} -s $$pktsize -c AES128-SHA -t ${TIME};\
done
throughput_AES128-SHA:
@echo "------------------------------------- Throughput Test -------------------------------------";
@echo "Server IP        Server Port        Thread Number        Times        Cipher        Version";
@echo "${THROUGHPUTIP}            ${PORT}                ${NUM_THREADS}       ${TIME}        AES128-SHA       SSLv3";
@echo "               Package Size(Bytes)        Operations        Throughtput(Mbps)";
for pktsize in ${PKT_SIZES}; do \
./client -m 1 -a ${THROUGHPUTIP} -l ${NUM_THREADS} -s $$pktsize -c AES128-SHA -t ${TIME} -e;\
done
throughput_AES256-SHA:
@echo "-------------------------------------------------------------------------------------------";
@echo "Server IP        Server Port        Thread Number        Times        Cipher        Version";
@echo "${THROUGHPUTIP}            ${PORT}                ${NUM_THREADS}       ${TIME}        AES256-SHA       SSLv3";
@echo "               Package Size(Bytes)        Operations        Throughtput(Mbps)";
for pktsize in ${PKT_SIZES}; do \
./client -m 1 -a ${THROUGHPUTIP} -l ${NUM_THREADS} -s $$pktsize -c AES256-SHA -t ${TIME} -e;\
done
throughput_RC4-SHA:
@echo "-------------------------------------------------------------------------------------------";
@echo "Server IP        Server Port        Thread Number        Times        Cipher        Version";
@echo "${THROUGHPUTIP}            ${PORT}                ${NUM_THREADS}       ${TIME}          RC4-SHA         SSLv3";
@echo "               Package Size(Bytes)        Operations        Throughtput(Mbps)";
for pktsize in ${PKT_SIZES}; do \
./client -m 1 -a ${THROUGHPUTIP} -l ${NUM_THREADS} -s $$pktsize -c RC4-SHA -t ${TIME} -e;\
done
throughput_RC4-MD5:
@echo "-------------------------------------------------------------------------------------------";
@echo "Server IP        Server Port        Thread Number        Times        Cipher        Version";
@echo "${THROUGHPUTIP}            ${PORT}                ${NUM_THREADS}       ${TIME}          RC4-MD5       SSLv3";
@echo "               Package Size(Bytes)        Operations        Throughtput(Mbps)";
for pktsize in ${PKT_SIZES}; do \
./client -m 1 -a ${THROUGHPUTIP} -l ${NUM_THREADS} -s $$pktsize -c RC4-MD5 -t ${TIME} -e;\
done
throughput_DES-CBC-SHA:
@echo "-------------------------------------------------------------------------------------------";
@echo "Server IP        Server Port        Thread Number        Times        Cipher        Version";
@echo "${THROUGHPUTIP}            ${PORT}                ${NUM_THREADS}       ${TIME}       DES-CBC-SHA       SSLv3";
@echo "               Package Size(Bytes)        Operations        Throughtput(Mbps)";
for pktsize in ${PKT_SIZES}; do \
./client -m 1 -a ${THROUGHPUTIP} -l ${NUM_THREADS} -s $$pktsize -c DES-CBC-SHA -t ${TIME} -e;\
done
throughput_DES-CBC3-SHA:
@echo "-------------------------------------------------------------------------------------------";
@echo "Server IP        Server Port        Thread Number        Times        Cipher        Version";
@echo "${THROUGHPUTIP}            ${PORT}                ${NUM_THREADS}       ${TIME}       DES-CBC3-SHA      SSLv3";
@echo "               Package Size(Bytes)        Operations        Throughtput(Mbps)";
for pktsize in ${PKT_SIZES}; do \
./client -m 1 -a ${THROUGHPUTIP} -l ${NUM_THREADS} -s $$pktsize -c DES-CBC3-SHA -t ${TIME} -e;\
done
handshake_server:
./server -l ${NUM_THREADSHS};
throughput_server:
@echo "------------------ Throughput Test ------------------";
@echo "Server Port        Thread Number        Package Size";
for var in ${LOOP}; do \
for pktsize in ${PKT_SIZES}; do \
./server -m 1 -l ${NUM_THREADS} -s $$pktsize -e;\
done \
done

run_client: throughput_AES128-SHA throughput_AES256-SHA throughput_RC4-SHA throughput_RC4-MD5 throughput_DES-CBC-SHA throughput_DES-CBC3-SHA handshake_client
run_server: throughput_server handshake_server

clean:
rm -f *.o server client

make_key.sh

#!/bin/sh
openssl genrsa -out privkey.pem 2048
openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: