高并发服务器

1.线程池

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <windows.h>
using namespace std;

#define sleep(n) Sleep(n*1000)

#define DEFAULT_TIME 10         /*10秒检测一次线程与任务的比例*/
#define MIN_WAIT_TASK_NUM  10     /*如果任务列表中等待处理的任务数超过一定量,则向线程池中添加线程*/
#define DEFAULT_THREAD_VARY 10  /*默认创建和销毁的线程的数目*/

typedef struct
{
    void *(*function)(void *);  /*函数指针,回调函数,处理的任务*/
    void *arg;                  /*上述函数的参数*/
}threadpool_task_t;             /*任务结构体*/

struct threadpool_t
{
    pthread_mutex_t lock;               /*用于锁住这个结构体*/
    pthread_mutex_t thread_counter;     /*访问忙线程个数的锁*/
    pthread_cond_t queue_not_full;      /*任务队列不满时*/
    pthread_cond_t queue_not_empty;     /*任务队列不为空时,通知等待获取任务的线程*/
    pthread_t *threads;                 /*保存工作线程tid的数组*/
    pthread_t adjust_tid;               /*管理线程tid*/
    threadpool_task_t *task_queue;      /*任务队列*/
    int min_thr_num;                    /*线程池中最小的线程个数*/
    int max_thr_num;                    /*线程池中最大的线程个数*/
    int live_thr_num;                   /*线程池当前拥有的线程个数*/
    int busy_thr_num;                   /*忙状态线程的个数*/
    int wait_exit_thr_num;              /*等待销毁的线程的个数*/
    int queue_front;                    /*任务队列头索引的下标*/
    int queue_rear;                     /*任务队列尾索引的下标*/
    int queue_size;                     /*任务队列中元素个数*/
    int queue_max_size;                 /*任务队列能容纳的最大任务数*/
    bool shutdown;                       /*线程池状态:是否关闭*/
};

void sys_err(char *str)
{
    perror(str);
    exit(1);
}

/*
线程池中其他线程需要完成的任务
*/
void *threadpool_thread(void *threadpool);

/*
线程池的管理线程需要完成的任务
*/
void *adjust_thread(void *threadpool);

/*
检查线程是否存活
*/
bool is_thread_alive(pthread_t pid);

int threadpool_free(threadpool_t *pool);

//创建线程池
threadpool_t *threadpool_create(int min_thr_num, int max_thr_num, int queue_max_size)
{
    int i;
    threadpool_t *pool = NULL;
    do{
        //动态内存申请失败(创建线程池失败)
        if((pool = (threadpool_t*)malloc(sizeof(threadpool_t))) == NULL)
        {
            printf("malloc threadpool fail.\n");
            break;
        }

        pool->min_thr_num = min_thr_num;
        pool->max_thr_num = max_thr_num;
        pool->busy_thr_num = 0;
        pool->live_thr_num = min_thr_num;
        pool->queue_size = 0;
        pool->queue_max_size = queue_max_size;
        pool->queue_front = 0;
        pool->queue_rear = 0;
        pool->shutdown = false;

        //为线程池添加线程
        pool->threads = (pthread_t*)malloc(sizeof(pthread_t)*max_thr_num);
        //线程创建失败
        if(pool->threads == NULL)
        {
            printf("malloc threads fail.\n");
            break;
        }
        memset(pool->threads, 0, sizeof(pool->threads));//第一个线程清0??

        pool->task_queue = (threadpool_task_t*)malloc(sizeof(threadpool_task_t)*queue_max_size);

        if(pool->task_queue == NULL)
        {
            printf("malloc task_queue fail.\n");
            break;
        }

        if(pthread_mutex_init(&(pool->lock), NULL) != 0
            || pthread_mutex_init(&(pool->thread_counter), NULL) != 0
            || pthread_cond_init(&(pool->queue_not_empty), NULL) != 0
            || pthread_cond_init(&(pool->queue_not_full), NULL) !=0 )
        {
            printf("init the lock or cond fail.\n");
            break;
        }

        //启动min_thr_num个工作线程
        for(i = 0;i<min_thr_num;i++)
        {
            pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void*)pool);
            printf("start thread 0x%x.\n", (unsigned int)pool->threads[i]);
        }
        //创建控制线程
        pthread_create(&(pool->adjust_tid), NULL, adjust_thread, (void*)pool);
        return pool;

    }while(0);

    threadpool_free(pool);
    return NULL;
}

//向任务列表中添加任务
int threadpool_add(threadpool_t *pool, void*(*function)(void *arg), void *arg)
{
    if(pool == NULL)
    {
        printf("thread pool is not inited.\n");
        return -1;
    }

    pthread_mutex_lock(&(pool->lock));

    while((pool->queue_size) >= (pool->queue_max_size) && !(pool->shutdown))
    {
        //任务列表满了,等待
        pthread_cond_wait(&(pool->queue_not_full), &(pool->lock));
    }

    if(pool->shutdown)
    {
        pthread_mutex_unlock(&(pool->lock));
        printf("Unable add task(threadpool exit).\n");
        return 0;
    }

    //添加任务到任务列表中
    if(pool->task_queue[pool->queue_rear].arg != NULL)
    {
        //防止内存泄漏
        free(pool->task_queue[pool->queue_rear].arg);
        pool->task_queue[pool->queue_rear].arg = NULL;
    }

    pool->task_queue[pool->queue_rear].function = function;
    pool->task_queue[pool->queue_rear].arg = arg;
    pool->queue_rear = (pool->queue_rear + 1) % (pool->queue_max_size);
    pool->queue_size++;

    //队列非空,发送信号
    pthread_cond_signal(&(pool->queue_not_empty));
    pthread_mutex_unlock(&(pool->lock));

    return 0;
}

void *threadpool_thread(void *threadpool)
{
    threadpool_t *pool = (threadpool_t*)threadpool;
    threadpool_task_t task;

    //开启线程后,会尝试拿锁,拿到锁后会判断任务队列是否有任务
    //若没有任务,会释放锁,并阻塞在信号量上,等待信号的唤醒
    while(true)
    {
        pthread_mutex_lock(&(pool->lock));

        while((pool->queue_size == 0) && (!pool->shutdown))
        {
            printf("thread 0x%x is waiting.\n", (unsigned int)pthread_self());
            pthread_cond_wait(&(pool->queue_not_empty), &(pool->lock));

            /*清除指定数目的空闲线程,如果要结束的线程个数大约0,结束线程*/
            if(pool->wait_exit_thr_num > 0)
            {
                //无论是否结束线程,都要减!!
                pool->wait_exit_thr_num--;
                //若线程个数大于最小线程数则停止该线程
                if(pool->live_thr_num > pool->min_thr_num)
                {
                    printf("thread 0x%x is exiting.\n", (unsigned int)pthread_self());
                    pool->live_thr_num--;
                    pthread_mutex_unlock(&(pool->lock));
                    pthread_exit(NULL);
                }
            }
        }

        //关闭线程池,处于空闲状态的线程需要接受信号量,处于忙状态的线程忙完之后还能执行到这里
        if(pool->shutdown)
        {
            pthread_mutex_unlock(&(pool->lock));
            printf("thread 0x%x is exiting.\n", (unsigned int)pthread_self());
            pthread_exit(NULL);
        }

        //从任务列表中取任务
        task.function = pool->task_queue[pool->queue_front].function;
        task.arg = pool->task_queue[pool->queue_front].arg;
        pool->queue_front = (pool->queue_front + 1) % pool->queue_max_size;
        pool->queue_size--;

        //这两句的顺序会有什么影响??
        pthread_mutex_unlock(&(pool->lock));
        pthread_cond_broadcast(&(pool->queue_not_full));

        //执行任务
        printf("thread 0x%x start working.\n", (unsigned int)pthread_self());
        pthread_mutex_lock(&(pool->thread_counter));
        pool->busy_thr_num++;
        pthread_mutex_unlock(&(pool->thread_counter));

        (*task.function)(task.arg);   //执行回调任务

        printf("thread 0x%x end working.\n", (unsigned int)pthread_self());
        pthread_mutex_lock(&(pool->thread_counter));
        pool->busy_thr_num--;
        pthread_mutex_unlock(&(pool->thread_counter));
    }

    return NULL;
}

void *adjust_thread(void *threadpool)
{
    threadpool_t *pool = (threadpool_t*)threadpool;
    int i;

    while(!pool->shutdown)
    {
        sleep(DEFAULT_TIME);
        pthread_mutex_lock(&(pool->lock));
        int queue_size = pool->queue_size;
        int live_thr_num = pool->live_thr_num;
        pthread_mutex_unlock(&(pool->lock));

        pthread_mutex_lock(&(pool->thread_counter));
        int busy_thr_num = pool->busy_thr_num;
        pthread_mutex_unlock(&(pool->thread_counter));

        //任务数超过一定的量,就要增加线程的个数
        //感觉这个判断条件并不是很准确~
        if(queue_size >= MIN_WAIT_TASK_NUM && live_thr_num < pool->max_thr_num)
        {
            pthread_mutex_lock(&pool->lock);
            int add = 0;
            //一次添加DEFAULT_THREAD_VERY个线程
            for(i = 0;i < pool->max_thr_num && add < DEFAULT_THREAD_VARY &&
                pool->live_thr_num < pool->max_thr_num; i++)

            {
                if(pool->threads[i] == 0 || !is_thread_alive(pool->threads[i]))
                {
                    pthread_create(&(pool->threads[i]), NULL, threadpool_thread, threadpool);
                    add++;
                    pool->live_thr_num++;
                }
            }
        }

        //空闲线程过多,销毁一部分线程
        if((busy_thr_num*2)<live_thr_num && live_thr_num > pool->min_thr_num)
        {
            pthread_mutex_lock(&(pool->lock));
            //一次删除DEFAULT_THREAD_VARY个线程,合理????
            //busy=3 live=7 删除10个??
            pool->wait_exit_thr_num = DEFAULT_THREAD_VARY;
            pthread_mutex_unlock(&(pool->lock));

            for(i = 0; i < DEFAULT_THREAD_VARY;i++)
            {
                //通知空闲线程结束
                pthread_cond_signal(&(pool->queue_not_empty));
            }
        }
    }
}

int threadpool_destroy(threadpool_t *pool)
{
    int i;
    if(pool == NULL)
    {
        return -1;
    }

    pool->shutdown = true;
    //销毁管理线程
    pthread_join(pool->adjust_tid, NULL);
    //通知所有的空闲线程,结束自己
    pthread_cond_broadcast(&(pool->queue_not_empty));
    //这个for好像没什么用
    for(i = 0; i < pool->min_thr_num;i++)
    {
        //pthread_join(pool->threads[i], NULL);
    }
    threadpool_free(pool);
    return 0;
}

int threadpool_free(threadpool_t *pool)
{
    if(pool == NULL)
    {
        return -1;
    }
    printf("-------------\n");
    if(pool->task_queue)
    {
        free(pool->task_queue);
    }
    if(pool->threads)
    {
        free(pool->threads);
        //如何销毁锁和信号量
        pthread_mutex_lock(&(pool->lock));
        pthread_mutex_destroy(&(pool->lock));
        pthread_mutex_lock(&(pool->thread_counter));
        pthread_mutex_destroy(&(pool->thread_counter));
        pthread_cond_destroy(&(pool->queue_not_empty));
        pthread_cond_destroy(&(pool->queue_not_full));
    }
    printf("-------------\n");
    free(pool);
    pool = NULL;
    return 0;
}

bool is_thread_alive(pthread_t tid)
{
    //向线程发送0号信号,判断线程是否存活
    int kill_rc = pthread_kill(tid, 0);
    if(kill_rc == ESRCH)
    {
        return false;
    }
    return true;
}

void *process(void *arg)
{
    printf("thread 0x%x is working on task %d\n", (unsigned int)pthread_self(), *((int *)arg));
    sleep(1);
    printf("task %d is end.\n", *((int*)arg));
    return NULL;
}

int main()
{
    threadpool_t *thp = threadpool_create(20, 100, 12);
    printf("pool inited.\n");

    int *num = (int*)malloc(sizeof(int)*100);
    int i;
    for(i=0;i<100;i++)
    {
        num[i] = i;
        printf("add task %d\n",i);
        threadpool_add(thp, process,(void*)&num[i]);
    }
    sleep(5);
    threadpool_destroy(thp);
    printf("threadpool_destroy end.\n");
    return 0;
}

2.epoll

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <netinet/in.h>

#define BUF_SIZE 1024 
#define SERVER_PORT 8001
#define OPEN_MAX 1024 

int main(void)
{
	struct sockaddr_in seraddr, clieaddr;
	int serverfd, clientfd, cliaddlen;
	struct epoll_event tep, ep[OPEN_MAX];
	int nready, i, fd_num = 1, client[OPEN_MAX]; 
	int efd;
	char ipstr[128];

	//1.socket
	serverfd = socket(AF_INET, SOCK_STREAM, 0);

	//2.bind
	bzero(&seraddr, sizeof(seraddr));
	seraddr.sin_family = AF_INET;
	seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
	seraddr.sin_port = htons(SERVER_PORT);
	bind(serverfd, (struct sockaddr *)&seraddr, sizeof(seraddr));

	//3.listen
	listen(serverfd, 128);

	for(i=0;i<OPEN_MAX;i++)
		client[i] = -1;

	if((efd = epoll_create(OPEN_MAX)) == -1)
	{
		perror("epoll error");
		exit(1);
	}

	tep.events = EPOLLIN; tep.data.fd = serverfd;
	if(epoll_ctl(efd, EPOLL_CTL_ADD, serverfd, &tep) == -1)
	{
		perror("epoll_ctl error");
		exit(1);
	}

	printf("Accept connection...\n");
	while(1)
	{
		if((nready = epoll_wait(efd, ep, OPEN_MAX, -1)) == -1)
		{
			perror("epoll_wait error");
			exit(1);
		}
		printf("somebody is coming~\n");

		for(i=0;i<nready;i++)
		{
			if(!(ep[i].events & EPOLLIN))
				continue;
			if(ep[i].data.fd == serverfd)
			{
				//4.accept
				cliaddlen = sizeof(clieaddr);
				clientfd = accept(serverfd, (struct sockaddr *)&clieaddr, &cliaddlen);
				printf("Connection create: %s:%d\n", inet_ntop(AF_INET, 
							&clieaddr.sin_addr.s_addr, ipstr, 128), ntohs(clieaddr.sin_port));
				//需要判断是否到了链接最大上限,没写
				fd_num++;
				if(fd_num == OPEN_MAX)
				{
					printf("Exceed biggest connection num.\n");
					exit(1);
				}

				tep.events = EPOLLIN; tep.data.fd = clientfd;

				if(epoll_ctl(efd, EPOLL_CTL_ADD, clientfd, &tep) == -1)
				{
					perror("epoll_ctl error");
					exit(1);
				}
			}else
			{
				clientfd = ep[i].data.fd;
				char buf[BUF_SIZE];
				int len = read(clientfd, buf, BUF_SIZE);
				if(len ==0)
				{
					if(epoll_ctl(efd, EPOLL_CTL_DEL, clientfd, NULL) == -1)
					{
						perror("epoll_ctl error");
						exit(1);
					}
					close(clientfd);
					fd_num--;
					printf("Lost connection.\n");
				}else
				{
					buf[len] = '\0';
					printf("Reveive:%s\n", buf);
					for(i=0;i<len;i++)
					{
						buf[i] = toupper(buf[i]);
					}
					write(clientfd, buf, len);
				}
			}
		}
	}

	close(serverfd);

	return 0;
}

3.select


#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define BUF_SIZE 1024 
#define SERVER_PORT 8001

int main(void)
{
	struct sockaddr_in seraddr, clieaddr;
	int serverfd, clientfd, cliaddlen, maxfd;
	int nready, i, client[FD_SETSIZE]; //FD_SETSIZE = 1024,client用于记录客户端文件描述符
	char ipstr[128];

	//1.socket
	serverfd = socket(AF_INET, SOCK_STREAM, 0);

	//2.bind
	bzero(&seraddr, sizeof(seraddr));
	seraddr.sin_family = AF_INET;
	seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
	seraddr.sin_port = htons(SERVER_PORT);
	bind(serverfd, (struct sockaddr *)&seraddr, sizeof(seraddr));

	//3.listen
	listen(serverfd, 128);

	maxfd = serverfd;

	for(i=0;i<FD_SETSIZE;i++)
		client[i] = -1;
	
	fd_set rset, allset; //监听的文件描述符表
	
	FD_ZERO(&allset);
	FD_SET(serverfd, &allset); //初始状态只监听服务端文件描述符

	printf("Accept connection...\n");
	while(1)
	{
		rset = allset;
		nready = select(maxfd+1, &rset, NULL, NULL, NULL); //阻塞在select,等待数据到达
		printf("somebody is coming~\n");
		if(nready < 0)
		{
			perror("select error");
			exit(1);
		}
		if(FD_ISSET(serverfd, &rset))
		{
			//4.accept
			cliaddlen = sizeof(clieaddr);
			clientfd = accept(serverfd, (struct sockaddr *)&clieaddr, &cliaddlen);
			printf("Connection create: %s:%d\n", inet_ntop(AF_INET, 
						&clieaddr.sin_addr.s_addr, ipstr, 128), ntohs(clieaddr.sin_port));
			for(i=0;i<FD_SETSIZE;i++) //找一个空闲的文件描述符
			if(client[i]<0){
				client[i] = clientfd;
				break;
			}
			//需要判断是否到了链接最大上限,没写
			if(i == FD_SETSIZE)
			{
				printf("Exceed biggest connection num.\n");
				exit(1);
			}

			FD_SET(clientfd, &allset);
			if(maxfd < clientfd) maxfd = clientfd;
			
			if(--nready == 0) continue;
		}

		
		//处理客户端请求
		for(i=0;i<FD_SETSIZE;i++)
		{
			if(client[i]<0) continue;
			clientfd = client[i];

			if(FD_ISSET(clientfd, &rset))
			{
				char buf[BUF_SIZE];
				int len = read(clientfd, buf, BUF_SIZE);
				if(len ==0)
				{
					close(clientfd);
					FD_CLR(clientfd, &allset);
					client[i] = -1;
					printf("Lost connection.\n");
				}else
				{
					printf("Reveive:%s\n", buf);
					for(i=0;i<len;i++)
					{
						buf[i] = toupper(buf[i]);
					}
					write(clientfd, buf, len);
				}
				if(--nready == 0) break;
			}
		}
	}

	close(serverfd);

	return 0;
}

client

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define BUF_SIZE 1024 
#define SERVER_PORT 8001
#define SERVER_IP "10.108.17.150"

int main(void)
{
	struct sockaddr_in seraddr;
	int serverfd;
	char buf[BUF_SIZE];

	//1.socket
	serverfd = socket(AF_INET, SOCK_STREAM, 0);

	//2.connect	
	bzero(&seraddr, sizeof(seraddr));
	seraddr.sin_family = AF_INET;
	inet_pton(AF_INET, SERVER_IP, &seraddr.sin_addr.s_addr);
	seraddr.sin_port = htons(SERVER_PORT);
	connect(serverfd, (struct sockaddr *)&seraddr, sizeof(seraddr));

	while(scanf("%s", buf)!=EOF)
	{
		//3.发送数据
		int len = strlen(buf);
		write(serverfd, buf, len);
		len = read(serverfd, buf, BUF_SIZE);
		printf("Receive:%s\n", buf);
	}

	close(serverfd);

	return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值