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