线程池服务程序设计(续)
来源:互联网 发布:大数据行业分析 编辑:程序博客网 时间:2024/06/05 21:56
设计一个线程池,大小为4,服务器的功能就是“加减乘除”,客户端只需输入相应的指令和两个数字,比如输入add,然后输入12,13,然后把相应的结构传送给服务器计算,服务器把结果传回。代码来自《LinuxC程序基础与实例讲解》中,只是做了部分修改:
server端:
#include <stdio.h>#include <stdlib.h>#include <string.h> #include <pthread.h> #include <errno.h>#include <netdb.h> #include <net/if.h>#include <sys/socket.h>#include <sys/types.h> #include <sys/ioctl.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/tcp.h> #include <arpa/inet.h> #include <signal.h> #define SERVER_PORT 5555#define MAX_NUM 4typedef struct mathopt{int oprate;float value1;float value2;}mopt;//every thread has this data structure typedef struct threadatom{int clientsocket; //标记可用套接字,only flag = 1,the socket can be used int flag;// 标记flag值:1 means the thread is in the working status and 0 means waiting }tatom;struct threadatom threadpoolatom[MAX_NUM];//threadpool array pthread_t threadid[MAX_NUM];//clean the threadpoolvoid cleanthreadpool(){int i;for(i = 0; i < MAX_NUM; i++){threadpoolatom[i].clientsocket = 0;threadpoolatom[i].flag = 0;threadid[i] = 0;}}//show the thread statusvoid showthreadstatus(){int i;for( i = 0; i < MAX_NUM; i++){//printf("i = %d:threadid [%d],clientsocket [%d],flag [%s] \n",i,threadid[i],threadpoolatom[i].clientsocket,threadpoolatom[i].flag>=1?"working":"waiting");printf("i = %d:threadid [%d],clientsocket [%d],flag [%s] \n",i,i,threadpoolatom[i].clientsocket,threadpoolatom[i].flag>=1?"working":"waiting");}}void* processthread(void *para){//int index = *((int *)para);static int flg = 1;int index = (int)para;struct threadatom *pthread = &threadpoolatom[index];printf("Entery the processthread %d and waiting\n",index);while(1){//the flag means the working status,if 1,then make it work,else make it waitif(threadpoolatom[index].flag){if (flg == 1){printf("Processthread %d connect and keep connecting!\n",index);flg = 0;}char buffer[1024];int iDataNum ;//recive--iniDataNum = recv(pthread->clientsocket,buffer,1024,0);int length = sizeof(struct mathopt);if(iDataNum < length){perror("error: Recv data !!!");pthread->clientsocket = 0;pthread->flag = 0;continue ;}struct mathopt *pMp = (struct mathopt *)buffer;float result = 0;if(pMp->oprate == 0){result = pMp->value1 + pMp->value2;}else if(pMp->oprate == 1){result = pMp->value1 - pMp->value2;}else if(pMp->oprate == 2){result = pMp->value1 * pMp->value2;}else if(pMp->oprate == 3){result = pMp->value1 / pMp->value2;}else if(pMp->oprate == 4){pthread->clientsocket = 0;pthread->flag = 0;printf("Processthread %d disconnect!\n",index);continue;}char buf[100];sprintf(buf,"%f",result);printf("v1:%f v2:%f o:%d r:%f task[%d] finished!\n",pMp->value1,pMp->value2,pMp->oprate,result,index);//send--outint error = send(pthread->clientsocket,buf,sizeof(buf),0);if(error < 0){close(pthread->clientsocket);pthread->clientsocket = 0;pthread->flag = 0;continue;}}else{//printf("sleep thread :%d\n",index);sleep(1) ;}}}int main(int argc, char const *argv[]){int serverSocket;struct sockaddr_in server_addr;struct sockaddr_in clientAddr;int addr_len = sizeof(clientAddr);//create server socketif((serverSocket = socket(AF_INET,SOCK_STREAM,0)) < 0){perror( "error: create server socket!!!");exit(EXIT_FAILURE);}//design the server address bzero(&server_addr,sizeof(server_addr));server_addr.sin_family =AF_INET;server_addr.sin_port = htons(SERVER_PORT);server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//bind the server socket if(bind(serverSocket,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0){perror("error: bind address !!!!");exit(EXIT_FAILURE);}//listen the server socket if(listen(serverSocket,5)<0){perror("error: listen !!!!");exit(EXIT_FAILURE);}// all above server express socket_initcleanthreadpool();int i;for( i = 0 ; i < MAX_NUM; i++){pthread_t temp;int err;printf("i = %d\n",i);//err = pthread_create(&temp, NULL, processthread, (void *)&i); //create thread err = pthread_create(&temp, NULL, processthread, (void *)i);if(err == 0)printf("thread[%d] start ok............\n",i);elseprintf("thread[%d] create failed\n",i);sleep(2);}printf("init threadpool status:\n");showthreadstatus();while(1){int clientsocket;printf("accetp conn.....\n");clientsocket = accept(serverSocket,(struct sockaddr *)&clientAddr,(socklen_t*)&addr_len);if(clientsocket < 0){perror("error: accept client socket !!!");continue;}printf("find pool.....\n");for( i = 0 ; i < MAX_NUM; i++){if(threadpoolatom[i].flag == 0){threadpoolatom[i].flag = 1;//fetch a socket from the finished listen queuethreadpoolatom[i].clientsocket = clientsocket;break;}}printf("now thread pool status:\n");showthreadstatus();}close(serverSocket);return 0;}
client端:
#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#include <netdb.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <unistd.h>#define PORT 5555#define SERVER_IP "127.0.0.1"typedef struct mathopt{int oprate;float value1;float value2;}mopt;void createopt(struct mathopt *pMp){printf("please input operand one:");scanf("%f",&(pMp->value1));printf("please input operand two:");scanf("%f",&(pMp->value2));}void help(){ printf("==================================================================\n"); printf("version:V1.0\n"); printf("author:my2005lb\n\n\n"); printf("%-12s %-12s\n","Command","Fuction"); printf("%-12s %-12s\n","add","Adder computing"); printf("%-12s %-12s\n","minus","Minus computing"); printf("%-12s %-12s\n","multiply","Multiply computing"); printf("%-12s %-12s\n","divide","Divide computing"); printf("%-12s %-12s\n","help","Print help information"); printf("%-12s %-12s\n","quit","Exit the program"); printf("==================================================================\n");}int main(int argc, char const *argv[]){struct sockaddr_in serverAddr;int clientSocket;char sendbuf[200];char recvbuf[200];char command[20];if((clientSocket=socket(AF_INET,SOCK_STREAM,0)) < 0){perror( "error: create socket!!!");return -1; }serverAddr.sin_family=AF_INET;serverAddr.sin_port=htons(PORT);serverAddr.sin_addr.s_addr=inet_addr(SERVER_IP);if(connect(clientSocket,( struct sockaddr * )&serverAddr,sizeof(serverAddr)) < 0){perror("error: connect remote server !!!");exit(1);}printf("infor: connect with destination host........[ok]\n");while(1){printf("Input your World:>");scanf("%s",command);struct mathopt mp;if(strcmp(command,"add") == 0){createopt(&mp);mp.oprate = 0;}else if(strcmp(command,"minus") == 0){createopt(&mp);mp.oprate = 1;}else if(strcmp(command,"multiply") == 0){createopt(&mp);mp.oprate = 2;}else if(strcmp(command,"divide") == 0){while(1){createopt(&mp);if(mp.value2 == 0){printf("warning: Dividend can not be 0!!!!!\n");}else{break;}}mp.oprate = 3;}else if(strcmp(command,"help") == 0){help();continue ;}else if(strcmp(command,"quit") == 0){mp.oprate = 4;}else{printf("error: can't identify your input !!!\n");continue ;}send(clientSocket,(char *)&mp,sizeof(mp),0);if(mp.oprate == 4){break;}recv(clientSocket,recvbuf,200,0);printf("the result is: %s\n",recvbuf);}close(clientSocket);return 0;}
有个问题:就是我只能四个客户端同时用,如果有第五个客户端联接进来,只能等待,但是当前4个客户端退出一个以后,我第五个客户端还是不能用这个退出的线程。所以代码有待改进!
服务端程序的一些改进:
参见http://blog.csdn.net/hubi0952/article/details/8045094
#include <stdio.h>#include <stdlib.h>#include <string.h> #include <pthread.h> #include <errno.h>#include <netdb.h> #include <net/if.h>#include <sys/socket.h>#include <sys/types.h> #include <sys/ioctl.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/tcp.h> #include <arpa/inet.h> #include <signal.h> #include <assert.h>/**线程池里所有运行和等待的任务都是一个CThread_worker*由于所有任务都在链表里,所以是一个链表结构*/typedef struct worker{ /*回调函数,任务运行时会调用此函数,注意也可声明成其它形式*/ void *(*processthread)(void *sock); /*回调函数的参数*/ void *sock; struct worker *next;} CThread_worker;typedef struct mathopt{ int oprate; float value1; float value2;}mopt;typedef struct threadatom{ int clientsocket; //标记可用套接字,only flag = 1,the socket can be used int flag;// 标记flag值:1 means the thread is in the working status and 0 means waiting }tatom;/*线程池结构*/typedef struct{ pthread_mutex_t queue_lock; pthread_cond_t queue_ready; /*链表结构,线程池中所有等待任务*/ CThread_worker *queue_head; /*是否销毁线程池*/ int shutdown; pthread_t *threadid; /*线程池中允许的活动线程数目*/ int max_thread_num; /*当前等待队列的任务数目*/ int cur_queue_size;} CThread_pool;#define SERVER_PORT 5555int pool_add_worker (void *(*processthread) (void *), void *);void *thread_routine (void *arg);//thread functionvoid *processthread(void *sock);//deal with the client message//share resourcestatic CThread_pool *pool = NULL;void pool_init (int max_thread_num){ pool = (CThread_pool *) malloc (sizeof (CThread_pool)); pthread_mutex_init (&(pool->queue_lock), NULL); pthread_cond_init (&(pool->queue_ready), NULL); pool->queue_head = NULL; pool->max_thread_num = max_thread_num; pool->cur_queue_size = 0; pool->shutdown = 0; pool->threadid = (pthread_t *) malloc (max_thread_num * sizeof (pthread_t)); int i; for (i = 0; i < max_thread_num; i++) { pthread_create (&(pool->threadid[i]), NULL, thread_routine, NULL); }}void *thread_routine (void *arg){ printf ("starting thread 0x%x\n", pthread_self ()); while (1) { pthread_mutex_lock (&(pool->queue_lock)); /*如果等待队列为0并且不销毁线程池,则处于阻塞状态; 注意 pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁*/ while (pool->cur_queue_size == 0 && !pool->shutdown) { printf ("thread 0x%x is waiting\n", pthread_self ()); pthread_cond_wait (&(pool->queue_ready), &(pool->queue_lock)); } /*线程池要销毁了*/ if (pool->shutdown) { /*遇到break,continue,return等跳转语句,千万不要忘记先解锁*/ pthread_mutex_unlock (&(pool->queue_lock)); printf ("thread 0x%x will exit\n", pthread_self ()); pthread_exit (NULL); } printf ("thread 0x%x is starting to work\n", pthread_self ()); /*assert是调试的好帮手*/ assert (pool->cur_queue_size != 0); assert (pool->queue_head != NULL); /*等待队列长度减去1,并取出链表中的头元素*/ pool->cur_queue_size--; CThread_worker *worker = pool->queue_head; pool->queue_head = worker->next; pthread_mutex_unlock (&(pool->queue_lock)); /*调用回调函数,执行任务*/ (*(worker->processthread)) (worker->sock); free (worker); worker = NULL; } /*这一句应该是不可达的*/ pthread_exit (NULL);}void* processthread(void *sock){ int clientsocket = *(int *)sock; printf("Entery the processthread and waiting\n"); while(1) { char buffer[1024]; int iDataNum ; //recive--in iDataNum = recv(clientsocket,buffer,1024,0); int length = sizeof(struct mathopt); if(iDataNum < length) { perror("error: Recv data !!!"); continue ; } struct mathopt *pMp = (struct mathopt *)buffer; float result = 0; if(pMp->oprate == 0) { result = pMp->value1 + pMp->value2; } else if(pMp->oprate == 1) { result = pMp->value1 - pMp->value2; } else if(pMp->oprate == 2) { result = pMp->value1 * pMp->value2; } else if(pMp->oprate == 3) { result = pMp->value1 / pMp->value2; } else if(pMp->oprate == 4) { printf("Processthread %d disconnect!\n",clientsocket);// continue; break; } char buf[100]; sprintf(buf,"%f",result); printf("v1:%f v2:%f o:%d r:%f task[%d] finished!\n",pMp->value1,pMp->value2,pMp->oprate,result,clientsocket); //send--out int error = send(clientsocket,buf,sizeof(buf),0); if(error < 0) { close(clientsocket);// continue; break; } } sleep(1) ;} /*向线程池中加入任务*/int pool_add_worker (void *(*process) (void *sock), void *sock){ /*构造一个新任务*/ CThread_worker *newworker = (CThread_worker *) malloc (sizeof (CThread_worker)); newworker->processthread = processthread; newworker->sock = (int *)sock; newworker->next = NULL;/*别忘置空*/ pthread_mutex_lock (&(pool->queue_lock)); /*将任务加入到等待队列中*/ CThread_worker *member = pool->queue_head; if (member != NULL) { while (member->next != NULL) member = member->next; member->next = newworker; } else { pool->queue_head = newworker; } assert (pool->queue_head != NULL); pool->cur_queue_size++; pthread_mutex_unlock (&(pool->queue_lock)); /*好了,等待队列中有任务了,唤醒一个等待线程; 注意如果所有线程都在忙碌,这句没有任何作用*/ pthread_cond_signal (&(pool->queue_ready)); return 0;}/*销毁线程池,等待队列中的任务不会再被执行,但是正在运行的线程会一直把任务运行完后再退出*/int pool_destroy (){ if (pool->shutdown) return -1;/*防止两次调用*/ pool->shutdown = 1; /*唤醒所有等待线程,线程池要销毁了*/ pthread_cond_broadcast (&(pool->queue_ready)); /*阻塞等待线程退出,否则就成僵尸了*/ int i; for (i = 0; i < pool->max_thread_num; i++) pthread_join (pool->threadid[i], NULL); free (pool->threadid); /*销毁等待队列*/ CThread_worker *head = NULL; while (pool->queue_head != NULL) { head = pool->queue_head; pool->queue_head = pool->queue_head->next; free (head); } /*条件变量和互斥量也别忘了销毁*/ pthread_mutex_destroy(&(pool->queue_lock)); pthread_cond_destroy(&(pool->queue_ready)); free (pool); /*销毁后指针置空是个好习惯*/ pool=NULL; return 0;}int main (int argc, char **argv){ //socket init int serverSocket; int clientsocket; struct sockaddr_in client_addr; struct sockaddr_in server_addr; int addr_len = sizeof(client_addr); //create the server socket if ((serverSocket = socket(AF_INET,SOCK_STREAM,0)) < 0) { perror("socket create failed !"); exit(EXIT_FAILURE); } //design the server address bzero(&server_addr,sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SERVER_PORT); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //bind the server socket if (bind(serverSocket,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0) { perror("bind the server socket failed!"); exit(EXIT_FAILURE); } //listen the server socket if (listen(serverSocket,5) < 0) { perror("listen server socket failed!"); exit(EXIT_FAILURE); } pool_init (3);/*线程池中最多三个活动线程*/ while(1) { clientsocket = accept(serverSocket,(struct sockaddr *)&client_addr,(socklen_t *)&addr_len); if (clientsocket < 0) { perror("clientsocket accept failed!"); continue; } pool_add_worker (processthread, &clientsocket); } /*等待所有任务完成*/ sleep (5); /*销毁线程池*/ pool_destroy (); return 0;}
- 线程池服务程序设计(续)
- 线程池服务程序设计
- 线程池服务模型
- 线程池管理服务
- java并发程序设计总结六:线程池
- Win32程序设计之服务
- Java后台服务程序设计
- Java后台服务程序设计
- Win32程序设计之服务
- Java 后台服务程序设计
- 中断服务程序设计实验
- java后台服务程序设计
- 多进程服务程序设计
- Windows程序设计 ---线程
- linux程序设计:POSIX线程
- Pthead 线程 -- 多线程程序设计
- Linux程序设计--线程
- Java高并发程序设计笔记(四)之线程池
- 特权位和粘贴位
- stm32_ps2键盘显示测试程序
- TypeScript Resources
- 趋势科技2011校招笔试题+答案解析
- linux 使用boost
- 线程池服务程序设计(续)
- 设计模式——创建型设计模式总结(简单工厂、普通工厂、抽象工厂、建造者、原型和单例)
- 华为2011上机笔试题3+参考程序
- Spring3+Hibernate4+SpringMVC整合Ext:开发Ext界面及Accordin Tree
- 【设计原则】面向对象编程的六大原则
- opencv2.2 MFC picture控件中显示图片
- 《android课表》之metro风格
- 浙江大华2012笔试题+答案解析
- ubuntu 12 中文输入法的安装