文章目录
实现流程
-
网络初始化,创建服务器socket,绑定服务器地址,返回服务器sock
-
epoll监听树初始化,创建监听树,监听服务器socket,返回监听树fd
-
pool初始化,pool创建存储空间,pool扩容/缩容参数初始化,pool任务tid数组创建存储空间,pool条件变量初始化,pool任务队列创建存储空间,相关参数初始化,循环创建最小数量任务。创建管理任务,创建打印任务;返回pool指针
-
epoll监听,如果线程池没有关闭循环监听,处理返回的就绪socket,如果是服务器sock,task添加为accept;如果不是,task添加为recv,处理完毕调用 producer将任务添加到线程执行。循环结束回收服务器sock
-
生产者添加任务,如果线程池在运行,检测。如果当前任务等一最大任务,队列满,生产者等待,如果线程池关闭,解锁。队伍不满,给队列头指针添加任务,头指针后移1,当前指针++,pthread_kill发送SIGUSR1打印消息,通知消费者唤醒,解锁。
-
消费者分离线程,取线程池参数,线程池没有关闭循环获取任务执行。加锁,如果cur不为0(不为空),唤醒消费者。如果线程池关闭,解锁退出。如果需要销毁当前线程,活跃数量-1,销毁数量-1,从线程tid数组中移除当前线程,释放锁,退出当前线程,发送SIGUSR1信号。
获取队列尾任务,队列尾+1,busy+1,唤醒生产者,解锁。执行任务,加锁,busy-1,发送SIGUSR1信号,解锁。
如果线程池关闭返回NULL
-
recv接收任务,取出参数客户sock,使用用户sock接收数据。如果接收成功,检查是否是time,是取时间,发送时间buf,不是时间,发送提示信息,清空接收buf,时间buf。如果接收失败,客户端退出,取消监听,关闭客户端sock,打印消息。
-
accept任务,取出服务器sock,接收连接,如果成功,添加监听,打印客户端连接ip
-
manager任务,线程分离,取出pool*。线程池没有关闭的时候,上锁,取出线程忙闲,大小,当前指针参数,解锁。如果当前数量>可用||忙占比>70%&&max>live+min,扩容min,循环如果tids数组不为空,循环添加min数量thread,live++,解锁。
如果现存>2倍忙&&现有-min>=min,缩容。加锁,exit+10,解锁,循环挂起消费者
如果线程池关闭,返回NULL
-
线程销毁,取出pool参数,销毁条件变量,销毁锁,释放队列,释放tids,释放pool
-
设置信号,备份信号。信号设为空,添加信号,设置屏蔽码并备份。
初始化网络,初始化epoll,初始化pool,开始epoll监听
如果线程池关闭,销毁线程。
-
打印线程池信息
-
打印线程。分离线程,取出pool参数。设置信号行为,设为空,处理函数设置为打印函数,参数设置为0。绑定信号SIGUSR1与信号行为,备份。设置信号屏蔽信息。
如果线程池没有关闭,休眠1s。如果关闭,线程退出。
pool.h
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <signal.h>
#include <sys/epoll.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
typedef struct
{
void* arg;
void* (*busines)(void*);
}bs_t;
typedef struct
{
int thread_shutdown;
int thread_alive;
int thread_busy;
int thread_max;
int thread_min;
int thread_killnum;
bs_t* queue;
int front;
int rear;
int qmax;
int cur;
pthread_t *ctids;
pthread_t mid;
pthread_cond_t notEmpty;
pthread_cond_t notFull;
}pool_t;
int epfd;
pthread_t ptid;
pthread_mutex_t lock;
pool_t* ptr;
int net_init(char* ip,int port);
int epoll_init(int sockfd,int listen_num);
void epoll_listen(int sockfd,pool_t* pt);
void producer_add(pool_t* pt,bs_t tmp);
pool_t* pool_init(int tmax,int tmin,int qmax);
void* manager(void* arg);
void* customer(void* arg);
void* recv_busines(void* arg);
void* accept_busines(void* arg);
void sig_usr(int n);
void* thread_printf(void* arg);
void thread_destroy(void* arg);
accept_task
#include <pool.h>
void* accept_busines(void* arg)
{
int sockfd=*(int*)arg;
int clientsock;
struct sockaddr_in clientaddr;
socklen_t len=sizeof(clientaddr);
if((clientsock=accept(sockfd,(struct sockaddr*)&clientaddr,&len))==-1)
{
perror("accept_busines accept failed");
exit(0);
}
char ip[16];
char response[1024];
bzero(response,1024);
bzero(ip,16);
struct epoll_event node;
node.data.fd=clientsock;
node.events=EPOLLIN|EPOLLET;
if((epoll_ctl(epfd,EPOLL_CTL_ADD,clientsock,&node))!=0)
{
perror("accept_busines epoll_ctl failed");
exit(0);
}
sprintf(response,"connection successful\n");
inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,ip,16);
send(clientsock,response,strlen(response),MSG_NOSIGNAL);
return NULL;
}
recv_task
#include <pool.h>
void *recv_busines(void* arg)
{
int sockfd=*(int*)arg;
ssize_t recvNum;
char recvBuf[1024];
char ctime[1024];
time_t tp;
char* msg="tryagain\n";
if((recvNum=recv(sockfd,recvBuf,sizeof(recvBuf),MSG_DONTWAIT))>0)
{
if((strcmp(recvBuf,"time\n"))==0)
{
tp=time(NULL);
ctime_r(&tp,ctime);
send(sockfd,ctime,strlen(ctime),MSG_NOSIGNAL);
}
else
{
send(sockfd,msg,strlen(msg),MSG_NOSIGNAL);
}
sleep(10);
bzero(ctime,sizeof(ctime));
bzero(recvBuf,sizeof(recvBuf));
}
else if(recvNum==0)
{
if((epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,NULL))==-1)
{
perror("recv_busines epoll_ctl del failed");
exit(0);
}
close(sockfd);
printf("client exit...\n");
}
}
net_init
#include <pool.h>
int net_init(char* ip,int port)
{
int sockfd;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("net_init socket failed");
return -1;
}
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(port);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
if((bind(sockfd,(struct sockaddr*)&addr,sizeof(addr)))==-1)
{
perror("net_init bind failed");
return -1;
}
listen(sockfd,128);
return sockfd;
}
pool_init
#include <pool.h>
pool_t* pool_init(int tmax,int tmin,int qmax)
{
pool_t* pt;
if((pt=(pool_t*)malloc(sizeof(pool_t)))==NULL)
{
printf("pool_init pool_t malloc failed\n");
return NULL;
}
pt->thread_shutdown=1;
pt->thread_alive=0;
pt->thread_busy=0;
pt->thread_max=tmax;
pt->thread_min=tmin;
pt->thread_killnum=0;
if((pt->queue=(bs_t*)malloc(sizeof(bs_t)*qmax))==NULL)
{
printf("pool_init bs_t* malloc failed\n");
return NULL;
}
pt->front=0;
pt->rear=0;
pt->qmax=qmax;
pt->cur=0;
if((pthread_cond_init(&pt->notEmpty,NULL)!=0)||(pthread_cond_init(&pt->notFull,NULL)!=0)||(pthread_mutex_init(&lock,NULL)!=0))
{
printf("pool_init cond or mutex init failed\n");
return NULL;
}
if((pt->ctids=(pthread_t*)malloc(sizeof(pthread_t)*tmax))==NULL)
{
printf("pool_init ctids malloc failed\n");
return NULL;
}
bzero(pt->ctids,sizeof(pthread_t)*tmax);
//yuchuangjian
int err;
for(int i=0;i<tmin;i++)
{
if((err=pthread_create(&pt->ctids[i],NULL,customer,(void*)pt))>0)
{
printf("pool_init pthread_create customer failed: %s\n",strerror(err));
return NULL;
}
++pt->thread_alive;
}
if((err=pthread_create(&pt->mid,NULL,manager,(void*)pt))>0)
{
printf("pool_init pthead_create manager failed: %s\n",strerror(err));
return NULL;
}
if((err=pthread_create(&ptid,NULL,thread_printf,(void*)pt))>0)
{
printf("pool_init pthread_create thread_printf failed: %s\n",strerror(err));
return NULL;
}
return pt;
}
producer
#include <pool.h>
void producer_add(pool_t* pt,bs_t tmp)
{
if(pt->thread_shutdown)
{
pthread_mutex_lock(&lock);
while(pt->cur==pt->qmax)
{
pthread_cond_wait(&pt->notFull,&lock);
if(!pt->thread_shutdown)
{
pthread_mutex_unlock(&lock);
printf("producer shut %d,exit...\n",pt->thread_shutdown);
exit(0);
}
}
pt->queue[pt->front].arg=tmp.arg;
pt->queue[pt->front].busines=tmp.busines;
pt->front=(pt->front+1)%pt->qmax;
++pt->cur;
pthread_kill(ptid,SIGUSR1);
pthread_mutex_unlock(&lock);
pthread_cond_signal(&pt->notEmpty);
}
}
comsumer
#include <pool.h>
void* customer(void* arg)
{
pthread_detach(pthread_self());
pool_t* pt=(pool_t*)arg;
while(pt->thread_shutdown)
{
pthread_mutex_lock(&lock);
while(pt->cur==0)
{
pthread_cond_wait(&pt->notEmpty,&lock);
if(!pt->thread_shutdown)
{
printf("customer shutdown %d failed\n",pt->thread_shutdown);
pthread_mutex_unlock(&lock);
exit(0);
}
if(pt->thread_killnum)
{
--pt->thread_alive;
--pt->thread_killnum;
int n=pthread_self();
for(int i=0;i<pt->thread_max;i++)
{
if(pt->ctids[i]==n)
{
pt->ctids[i]=0;
break;
}
}
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
pthread_kill(ptid,SIGUSR1);
}
}
bs_t tmp;
//huoqurenwu
tmp.arg=pt->queue[pt->rear].arg;
tmp.busines=pt->queue[pt->rear].busines;
pt->rear=(pt->rear+1)%pt->qmax;
--pt->cur;
++pt->thread_busy;
pthread_kill(ptid,SIGUSR1);
pthread_mutex_unlock(&lock);
pthread_cond_signal(&pt->notFull);
//zhixingrenwu
tmp.busines(tmp.arg);
pthread_mutex_lock(&lock);
--pt->thread_busy;
pthread_kill(ptid,SIGUSR1);
pthread_mutex_unlock(&lock);
}
return NULL;
}
manager
#include <pool.h>
void* manager(void* arg)
{
pthread_detach(pthread_self());
pool_t* pt=(pool_t*)arg;
int alive,busy,cur,tmax,tmin;
while(pt->thread_shutdown)
{
pthread_mutex_lock(&lock);
alive=pt->thread_alive;
busy=pt->thread_busy;
cur=pt->cur;
tmax=pt->thread_max;
tmin=pt->thread_min;
pthread_mutex_unlock(&lock);
int flag,add;
//kuorong
int err;
if((cur>=alive-busy||(double)busy/alive*100>=70)&&alive+tmin<=tmax)
{
for(flag=0,add=0;flag<tmax&&add<tmin;flag++)
{
if(pt->ctids[flag]==0)
{
pthread_mutex_lock(&lock);
if((err=pthread_create(&pt->ctids[flag],NULL,customer,(void*)pt))>0)
{
printf("manager pthread_create failed: %s\n",strerror(err));
pthread_mutex_unlock(&lock);
}
++pt->thread_alive;
pthread_mutex_unlock(&lock);
++add;
}
}
}
//suojian
if(alive-busy>=2*busy && alive-tmin>=tmin)
{
pthread_mutex_lock(&lock);
pt->thread_killnum=pt->thread_min;
pthread_mutex_unlock(&lock);
for(int i=0;i<tmin;i++)
{
pthread_cond_signal(&pt->notEmpty);
}
}
}
return NULL;
}
epoll_init
#include <pool.h>
int epoll_init(int sockfd,int listen_num)
{
if((epfd=epoll_create(listen_num))==-1)
{
perror("epoll_init epoll_create failed");
return -1;
}
struct epoll_event node;
node.data.fd=sockfd;
node.events=EPOLLIN|EPOLLET;
if((epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&node))==-1)
{
perror("epoll_init epoll_ctl failed");
return -1;
}
return 0;
}
epoll_listen
#include <pool.h>
void epoll_listen(int sockfd,pool_t *pt)
{
int readyNum;
struct epoll_event readyArray[100000];
int flag;
bs_t tmp;
while(pt->thread_shutdown)
{
if((readyNum=epoll_wait(epfd,readyArray,100000,-1))==-1)
{
perror("epoll_listen epoll_wait failed");
exit(0);
}
flag=0;
while(readyNum)
{
if(readyArray[flag].data.fd==sockfd)
{
tmp.arg=(void*)&readyArray[flag].data.fd;
tmp.busines=accept_busines;
}
else
{
tmp.arg=(void*)&readyArray[flag].data.fd;
tmp.busines=recv_busines;
}
producer_add(pt,tmp);
--readyNum;
++flag;
}
}
close(sockfd);
exit(0);
}
thread_printf
#include <pool.h>
void* thread_printf(void* arg)
{
pthread_detach(pthread_self());
ptr=(pool_t*)arg;
struct sigaction act,oact;
sigemptyset(&act.sa_mask);
act.sa_handler=&sig_usr;
act.sa_flags=0;
sigaction(SIGUSR1,&act,&oact);
sigprocmask(SIG_SETMASK,&act.sa_mask,NULL);
while(ptr->thread_shutdown)
{
sleep(1);
}
pthread_exit(NULL);
}
thread_destroy
#include <pool.h>
void thread_destroy(void* arg)
{
pool_t* pt=(pool_t*)arg;
pthread_cond_destroy(&pt->notEmpty);
pthread_cond_destroy(&pt->notFull);
pthread_mutex_destroy(&lock);
free(pt->queue);
free(pt->ctids);
free(pt);
}
sig_usr
#include <pool.h>
void sig_usr(int n)
{
printf("alive %d , busy %d , idel %d , cur %d , a/m %.2f%% , b/a %.2f%%\n",ptr->thread_alive,ptr->thread_busy,ptr->thread_alive-ptr->thread_busy,ptr->cur,(double)ptr->thread_alive/ptr->thread_max*100,(double)ptr->thread_busy/ptr->thread_alive*100);
}
main
#include <pool.h>
int main(void)
{
sigset_t set,oset;
sigemptyset(&set);
sigaddset(&set,SIGUSR1);
sigprocmask(SIG_SETMASK,&set,&oset);
int sockfd=net_init(NULL,8080);
pool_t* pt;
epoll_init(sockfd,100000);
pt=pool_init(100,10,1000);
epoll_listen(sockfd,pt);
if(!pt->thread_shutdown)
{
thread_destroy((void*)pt);
}
return 0;
}
client.c
#include<sock.h>
#define server_ip "192.168.206.150"
#define server_port 8080
int main()
{
struct sockaddr_in addr;
bzero(&addr,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(server_port);
addr.sin_addr.s_addr=inet_addr(server_ip);
// 创建套接字
int sock=SOCKET(AF_INET,SOCK_STREAM,0);
// 连接服务器
int err=CONNECT(sock,(struct sockaddr*)&addr,sizeof(addr));
if(err==-1)
{
// 若连接失败,关闭套接字并退出程序
close(sock);
exit(0);
}
char buf[1500];
// 清空缓冲区
bzero(buf,1500);
// 接收服务器的首次响应
RECV(sock,buf,sizeof(buf),0);
printf("%s\n",buf);
while(1)
{
// 清空缓冲区
bzero(buf,sizeof(buf));
if(fgets(buf,sizeof(buf),stdin)==NULL)
// 若读取输入失败,退出循环
break;
// 发送请求到服务器
SEND(sock,buf,strlen(buf),0);
// 清空缓冲区
bzero(buf,sizeof(buf));
// 接收服务器响应
RECV(sock,buf,sizeof(buf),0);
printf("%s\n",buf);
}
// 关闭套接字
close(sock);
return 0;
}
346

被折叠的 条评论
为什么被折叠?



