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