[TCP/IP网络编程]线程池实现回射服务器

github地址:https://github.com/Tangupton/socket-ThreadPool

 

1、threapool.h

#ifndef THREADPOOL_H
#define THREADPOOL_H

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

/*
 *线程体结构体
 */
typedef struct runner
{
	void* (*callback)(void*arg);
	void* arg;
	struct runner *next;
}thread_runner;


/*
 *线程池结构
 */
typedef struct 
{
	pthread_mutex_t mutex;
	pthread_cond_t cond;
	//线程池所有等待队列的头指针
	thread_runner* runner_head;
	//线程池所有等待队列的尾指针
	thread_runner* runner_tail;
	//所有线程
	pthread_t* threads;
	//线程池能活动的线程数量
	int max_thread_size;
	//线程池是否销毁
	int shutdown;
}thread_pool;

/*
 *线程执行任务
 */
void run(void* arg);

/*
 *初始化线程池
参数
pool:指向线程池结构有效地址的指针
max_thread_size:初始化线程池的大小
 */
void thread_pool_init(thread_pool* pool,int max_thread_size);

/*
 *向线程池加入任务
 参数
 pool:指向线程池结构有效地址的指针
 callback:回调函数
 arg;回调函数参数
 */
void threadpool_add_runner(thread_pool* pool,void*(*callback)(void* arg),void* arg);

/*
 *销毁线程池
 */
void thread_destroy(thread_pool** ppool);

#endif

2、threadpool.c

#include "threadPool.h"

#define DEBUG

/*
 *初始化线程池
 */
void thread_pool_init(thread_pool* pool,int max_thread_size)
{
	//初始化互斥量
	pthread_mutex_init(&(pool->mutex),NULL);
	//初始化条件变量
	pthread_cond_init(&(pool->cond),NULL);
	pool->runner_head = NULL;
	pool->runner_tail = NULL;
	pool->max_thread_size = max_thread_size;
	pool->shutdown = 0;

	//创建所有分离态线程
	pool->threads = (pthread_t*)malloc(max_thread_size*sizeof(pthread_t));
	for(int i = 0;i<max_thread_size;i++)
	{
		pthread_attr_t attr;
		pthread_attr_init(&attr);
		pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
		pthread_create(&(pool->threads[i]),&attr,(void*)run,(void*)pool);
	}
#ifdef DEBUG
	printf("thread_pool_create %d detached thread\n",max_thread_size);
#endif
}

/*
 *线程体
 */
void run(void* arg)
{
	thread_pool* pool = (thread_pool*)arg;
	while(1)
	{
		//加锁
		pthread_mutex_lock(&(pool->mutex));
#ifdef DEBUG
		printf("run->lock\n");
#endif
		//如果等待队列为0并且线程池未销毁,则阻塞
		while(pool->runner_head == NULL&&!pool->shutdown)
		{
			pthread_cond_wait(&(pool->cond),&(pool->mutex));
		}

		//如果线程池已经销毁
		if(pool->shutdown)
		{
			//解锁
			pthread_mutex_unlock(&(pool->mutex));
#ifdef DEBUG
			printf("run->lock and thread exit\n");
#endif
			//线程推出
			pthread_exit(NULL);	
		}

		//取得任务队列中的第一个任务
		thread_runner* runner = pool->runner_head;
		pool->runner_head = runner->next;
		pthread_mutex_unlock(&(pool->mutex));
#ifdef DEBUG
		printf("run->unlock\n");
#endif
		//调用回调(执行任务)
		(runner->callback)(runner->arg);
		free(runner);
		runner = NULL;
#ifdef DEBUG
		printf("run->runned and free runner\n");
#endif
	}
	pthread_exit(NULL);
}

/*
 *向线程池添加任务
 */
void threadpool_add_runner(thread_pool* pool,void*(*callback)(void* arg),void* arg)
{
	//构造一个新任务
	thread_runner* newrunner = (thread_runner*)malloc(sizeof(thread_runner));
	newrunner->callback = callback;
	newrunner->arg = arg;
	newrunner->next = NULL;

	//上锁,把新任务插入任务队列中
	pthread_mutex_lock(&(pool->mutex));
#ifdef DEBUG
	printf("threadpool_add_runner->locked\n");
#endif
	if(pool->runner_head != NULL)
	{
		pool->runner_tail->next = newrunner;
		pool->runner_tail = newrunner;
	}
	else
	{
		pool->runner_head = newrunner;
		pool->runner_tail = newrunner;
	}
	//解锁
	pthread_mutex_unlock(&(pool->mutex));
#ifdef DEBUG
	printf("threadpool_add_runner->unlocked\n");
#endif
	//唤醒等待队列
	pthread_cond_signal(&(pool->cond));
#ifdef DEBUG
	printf("threadpool_add_runner->add a runner and wakeip a waiting thread\n");
#endif
}

/*
*销毁线程
 */
void thread_destroy(thread_pool** ppool)
{
	thread_pool* pool = *ppool;
	//防止二次销毁
	if(!pool->shutdown)
	{
		pool->shutdown = 1;
		//唤醒所有等待队列,线程池要销毁了
		pthread_cond_broadcast(&(pool->cond));
		sleep(1);
#ifdef DEBUG 
		printf("threadpool_destroy->wakeup all waiting thread\n");
#endif
		//回收线程
		free(pool->threads);
		//销毁等待队列
		thread_runner *head = NULL;
		while(pool->runner_head != NULL)
		{
			head = pool->runner_head;
			pool->runner_head = pool->runner_head->next;
			free(head);
		}
#ifdef DEBUG
		printf("threadpool_destroy->all runner freed\n");
#endif
		//销毁:条件变量和互斥量
		pthread_mutex_destroy(&(pool->mutex));
		pthread_cond_destroy(&(pool->cond));
#ifdef DEBUG
		printf("threadpool_destroy->mutex and cond destoryed\n");
#endif
		free(pool);
		(*ppool) = NULL;
#ifdef DEBUG
		printf("threadpool_destroy->pool freed\n");
#endif
	}
}

 

3、serv.c

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

#define ser_ip "127.0.0.1"
#define ser_port 3698
#define max_thread_size 20  //初始化线程池的大小

/*
 *执行线程的参数(一个结构体)
 */
struct info
{
	int client_sock;                
	struct sockaddr_in client_addr;
};

/*
 *线程的工作(接受客户端的数据并返回小写)
 */
void* do_work(void* arg)
{
	char buf[BUFSIZ],str[BUFSIZ];
	struct info* ts = (struct info*)arg;

	//打印客户端的信息
	printf("======the connect client ip %s,port %d\n",
					inet_ntop(AF_INET,&(*ts).client_addr.sin_addr.s_addr,str,sizeof(str)),
					ntohs((*ts).client_addr.sin_port));
	while(1)
	{
		int len = read(ts->client_sock,buf,sizeof(buf));
		
		if(len == 0)
		{
			close(ts->client_sock);
			break;
		}
		else if(len>0)
		{
			for(int i = 0;i<len;i++)
				buf[i] = toupper(buf[i]);
			write(ts->client_sock,buf,len);
		}
	}
	return NULL;
}

int main()
{
	struct sockaddr_in ser_addr,client_addr;
	int serv_sock,client_sock;
	socklen_t client_sz; 
	thread_pool * pool;
	struct info ts[256];
	int i = 0;

	pool = (thread_pool*)malloc(max_thread_size*sizeof(thread_pool));

	serv_sock = socket(AF_INET,SOCK_STREAM,0);
	bzero(&ser_addr,sizeof(ser_addr));
	ser_addr.sin_family = AF_INET;
	ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	ser_addr.sin_port = htons(ser_port);

	thread_pool_init(pool,max_thread_size);
	
	if(bind(serv_sock,(struct sockaddr*)& ser_addr,sizeof(ser_addr)) == -1)
	{
		perror("bind() ");
		exit(1);
	}

	if(listen(serv_sock,20) == -1)
	{
		perror("listen() ");
		exit(1);
	}

	//while(int j = 0;j<max_thread_size;j++)
	while(1)
	{
		client_sz = sizeof(client_addr);
		client_sock = accept(serv_sock,(struct sockaddr*)& ser_addr,&client_sz);
		ts[i].client_sock = client_sock;
		ts[i].client_addr = client_addr;

		//把连接的客户端加入给等待队列中的线程处理
		threadpool_add_runner(pool,do_work,(void*)&ts[i]);
		i++;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值