并发服务器

火影  论坛元老 | 2024-8-31 19:11:20 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1017|帖子 1017|积分 3051

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
服务器,配景服务软件,后端开发,为软件客户端提供支持,数据支持,存储支持,数据中转
高并发要求,随着用户数目的增长,服务器的计划结构扩展,为更多用户提供服务器。
Web服务器(网页网站的后端都是web服务器),软件服务器(手机软件或者pc软件)。
开源服务器软件Apache,Nginx,用户配置即可使用,提供web服务器。
关于网页网站二点技术标准:共用协议(http https),超文本标记语言html,端标语共享使用http=80 https=443。
软件服务器,因不同软件不同功能,服务器的结构也不同,所以很难开源,因为并不适用其他软件。
后端开发的操作体系(服务器操作体系),Linux,Unix,window server,大多数都是控制台体系。
服务器集群:1.处理服务器(128核),2.图形处理器(GPU)渲染或图形盘算,3.数据库服务器 多版本数据库兼容。4.文件存储体系。
搭建集群的本钱比力高。
服务器的焦点使命,网络穿透。
服务器作为信息中转站,帮助所有用户转接数据,变更网络情况,用户重新毗连服务器,重新提交信息,服务器实时更新客户端的网络信息。
代理服务器

哀求与响应(Request/Response)一次交互。
代理服务器可以作为过滤层,摆设防火墙,防DOS攻击等等,隐藏主服务器。
横向扩展服务器硬件,分布式结构。分布式管理程序:资源共享,资源利用最大化,让每台处理机统一分配管理与调度,成为一个个体。
负载平衡概念:将大量的业务哀求匀称分发给n个处理单元。制止某些处理单元过载,制止某些处理单元长期闲置。
轮询分发(逐个分发)
根据处理单元的负载情况,决定如何分配。
心跳机制 Keep_alive

心跳测试,在一个时间段内,要通过心跳测试测试对端存活是否有效,有效保持毗连,无效断开毗连。
操作体系自带心跳机制(setsocketopt),这个心跳机制默认下要很久才能检测出对端是否断开。
如果一个毗连,一段时间没有交互,会被冷处理,通过间隔收发心跳包,让毗连保持活性,制止被冷处理。
单历程服务器

毗连部门,业务处理部门,协议解析部门。毗连部门和业务处理部门都是阻塞的,哀求时无法毗连,等待毗连时无法读取哀求。
单历程服务端,满意根本tcp毗连,完成简单的数据交互,对于体系时间的哀求和响应。
htons();将 16 位的短整数(如端标语)从主机字节顺序转换为网络字节顺序。
htonl();将 32 位整数从主机字节顺序转换为网络字节顺序。
INADDR_ANY,服务器将绑定到所有可用的网络接口上。这意味着服务器将接受任何网卡或接口上的毗连,而不限定于一个特定的 IP 地址。
bind()用于将一个套接字绑定到一个特定的地址和端口。绑定操作告诉操作体系,当有数据到达这个特定的 IP 地址和端口时,应该将数据交给这个套接字处理。
单历程阻塞

服务端:
  1. #include<stdio.h>
  2. #include<sys/fcntl.h>
  3. #include<sys/types.h>
  4. #include<sys/stat.h>
  5. #include<time.h>
  6. #include<string.h>
  7. #include<arpa/inet.h>
  8. #include<sys/socket.h>
  9. #include<unistd.h>
  10. #include<stdlib.h>
  11. int init_net()
  12. {
  13.     int sock;
  14.     struct sockaddr_in sockaddr;
  15.     bzero(&sockaddr,sizeof(sockaddr));
  16.     sockaddr.sin_family=AF_INET;
  17.     sockaddr.sin_port=htons(1234);
  18.     sockaddr.sin_addr.s_addr=htonl(INADDR_ANY);
  19.     if((sock=socket(AF_INET,SOCK_STREAM,0))==-1)
  20.         printf("socket error\n");
  21.     else printf("socket ok\n");
  22.     if((bind(sock,(struct sockaddr*)&sockaddr,sizeof(sockaddr)))==-1)
  23.     {
  24.         perror("bind error\n");
  25.     }
  26.     else printf("bind ok\n");
  27.     listen(sock,128);
  28.     return sock;
  29. }
  30. void mess_response(int so,struct sockaddr_in addr)
  31. {
  32.     char s[1024];
  33.     char c[16];
  34.     bzero(c,16);
  35.     bzero(s,1024);
  36.     inet_ntop(AF_INET,&addr.sin_addr,c,16);
  37.     sprintf(s,"hi %s\n",c);
  38.     int t=send(so,s,strlen(s),MSG_NOSIGNAL);
  39.     if(t<0)
  40.     {
  41.     perror("err");
  42.     }
  43.     return;
  44. }
  45. int recv_request(int sock)
  46. {
  47.     char s[1024];
  48.     char tim[1024];
  49.     bzero(s,sizeof(s));
  50.     bzero(tim,sizeof(tim));
  51.     int len;
  52.     time_t tp;
  53.     while((len=recv(sock,s,sizeof(s),0))>0)
  54.     {
  55.     s[strlen(s)-1]='\0';
  56.     if(strncmp(s,"time",strlen(s))==0)
  57.     {
  58.         tp=time(NULL);
  59.         ctime_r(&tp,tim);
  60.         send(sock,tim,strlen(tim),MSG_NOSIGNAL);
  61.     }
  62.     else{
  63.         send(sock,"try again",9,MSG_NOSIGNAL);
  64.     }
  65.     bzero(s,sizeof(s));
  66.     bzero(tim,sizeof(tim));
  67.     }
  68.     if(len==0)
  69.     {
  70.         printf("client sock %d its exiting...\n",sock);
  71.         close(sock);
  72. }
  73. }
  74. int main()
  75. {
  76.     int sock,csock;
  77.     struct sockaddr_in sock_client;
  78.     bzero(&sock_client,sizeof(sock_client));
  79.     sock=init_net();
  80.     printf("init ok\n");
  81.     socklen_t socklen;
  82.     while(1)
  83.     {
  84.     socklen=sizeof(sock_client);
  85.    if(( csock=(accept(sock,(struct sockaddr*)&sock_client,&socklen)))==-1)
  86.     perror("err\n");
  87.    else{
  88.        printf("accept success\n");
  89.    }
  90.     mess_response(csock,sock_client);
  91.     recv_request(csock);
  92.     }
  93.     close(csock);
  94.     close(sock);
  95.     return 0;
  96. }
复制代码
客户端:
  1. #include<stdio.h>
  2. #include<unistd.h>
  3. #include<stdlib.h>
  4. #include<arpa/inet.h>
  5. #include<signal.h>
  6. #include<sys/socket.h>
  7. #include<sys/fcntl.h>
  8. #include<string.h>
  9. int main()
  10. {
  11.     int sock;
  12.     struct sockaddr_in serveraddr;
  13.     serveraddr.sin_family=AF_INET;
  14.     serveraddr.sin_port=htons(1234);
  15.     inet_pton(AF_INET,"127.0.0.1",&serveraddr.sin_addr.s_addr);
  16.     if((sock=socket(AF_INET,SOCK_STREAM,0))==-1)
  17.     {
  18.         printf("socket error\n");
  19.     }
  20.     else printf("socket success\n");
  21.     if((connect(sock,(struct sockaddr*)&serveraddr,sizeof(serveraddr)))==-1)
  22.     {
  23.         printf("connect error\n");
  24.     }
  25.     else{
  26.         printf("connect success\n");
  27.     }
  28.     char buff[1024];
  29.     bzero(buff,1024);
  30.     int r=recv(sock,buff,sizeof(buff),0);
  31.     printf("%d\n",r);
  32.     //if((recv(sock,buff,sizeof(buff),0))==-1)
  33.     //{
  34.       //  perror("recv error\n");
  35.     //}
  36.     //else printf("recv ok\n");
  37.     printf("%s\n",buff);
  38. bzero(buff,1024);
  39.     while((fgets(buff,sizeof(buff),stdin))!=NULL)
  40.     {
  41.         send(sock,buff,strlen(buff),MSG_NOSIGNAL);
  42.         bzero(buff,1024);
  43.         recv(sock,buff,sizeof(buff),0);
  44.         printf("%s\n",buff);
  45.     }
  46.     close(sock);
  47.     return 0;
  48. }
复制代码

单历程非阻塞轮询模子

服务端:
  1. #include<stdio.h>
  2. #include<sys/fcntl.h>
  3. #include<sys/types.h>
  4. #include<sys/stat.h>
  5. #include<time.h>
  6. #include<string.h>
  7. #include<arpa/inet.h>
  8. #include<sys/socket.h>
  9. #include<unistd.h>
  10. #include<stdlib.h>
  11. #include<fcntl.h>
  12. #include<sys/types.h>
  13. #include<sys/stat.h>
  14. #include<errno.h>
  15. int clientsock[10000];
  16. int init_net();
  17. void mess_response(int,struct sockaddr_in);
  18. int recv_request(int);
  19. int start_server();
  20. #include<server.h>
  21. void mess_response(int so,struct sockaddr_in addr)
  22. {
  23.         char s[1024];
  24.         char c[16];
  25.         bzero(c,16);
  26.         bzero(s,1024);
  27.         inet_ntop(AF_INET,&addr.sin_addr,c,16);
  28.          sprintf(s,"hi %s\n",c);
  29.           int t=send(so,s,strlen(s),MSG_NOSIGNAL);
  30.           if(t<0)perror("err");
  31.           return;
  32. }
  33. #include<server.h>
  34. int recv_request(int sock)
  35. {
  36.         char s[1024];
  37.         char tim[1024];
  38.         bzero(s,sizeof(s));
  39.         bzero(tim,sizeof(tim));
  40.         int len;
  41.         time_t tp;
  42.         int i=0;
  43.         for(i;i<10000;i++)
  44.         {
  45.         if(clientsock[i]!=-1)
  46.         {
  47.         if((len=recv(clientsock[i],s,sizeof(s),MSG_DONTWAIT))>0)
  48.         {
  49.         s[strlen(s)-1]='\0';
  50.         if(strncmp(s,"time",strlen(s))==0)
  51.         {
  52.                 tp=time(NULL);
  53.                 ctime_r(&tp,tim);
  54.                 send(clientsock[i],tim,strlen(tim),MSG_NOSIGNAL);
  55.         }
  56.         else{
  57.                 send(clientsock[i],"try again",9,MSG_NOSIGNAL);
  58.         }
  59.         bzero(s,sizeof(s));
  60.         bzero(tim,sizeof(tim));
  61.         }
  62.         if(len==0)
  63.         {
  64.                 printf("client sock %d its exiting...\n",sock);
  65.                 close(clientsock[i]);
  66.                 clientsock[i]=-1;
  67.         }
  68.         }
  69.         }
  70. }
  71. #include<server.h>
  72. int server_start()
  73. {
  74.         int sock,csock;
  75.         struct sockaddr_in sock_client;
  76.         int i;
  77.         for(i=0;i<10000;i++)
  78.         clientsock[i]=-1;
  79.         bzero(&sock_client,sizeof(sock_client));
  80.         sock=init_net();
  81.         printf("init ok\n");
  82.         int flag;
  83.         fcntl(sock,F_GETFL,&flag);
  84.         flag|=O_NONBLOCK;
  85.         fcntl(sock,F_SETFL,flag);
  86.         socklen_t socklen;
  87.         while(1)
  88.         {
  89.         socklen=sizeof(sock_client);
  90.         if(( csock=(accept(sock,(struct sockaddr*)&sock_client,&socklen)))>0)
  91.            {
  92.                 for(i=0;i<10000;i++)
  93.            {
  94.                 if(clientsock[i]==-1)
  95.                 {
  96.                 clientsock[i]=csock;
  97.                 break;
  98.                 }
  99.            }
  100.            mess_response(csock,sock_client);
  101.            printf("accept success\n");
  102.          }
  103.         if(csock==-1)
  104.         {
  105.         if(errno==EAGAIN)
  106.         recv_request(csock);
  107.         else perror("accept call failed\n");
  108.         }
  109.         }
  110.         close(csock);
  111.         close(sock);
  112. }
  113. #include<server.h>
  114. int init_net()
  115. {
  116. int sock;
  117. struct sockaddr_in sockaddr;
  118. bzero(&sockaddr,sizeof(sockaddr));
  119. sockaddr.sin_family=AF_INET;
  120. sockaddr.sin_port=htons(1234);
  121. sockaddr.sin_addr.s_addr=htonl(INADDR_ANY);
  122. if((sock=socket(AF_INET,SOCK_STREAM,0))==-1)
  123. printf("socket error\n");
  124. else printf("socket ok\n");
  125. if((bind(sock,(struct sockaddr*)&sockaddr,sizeof(sockaddr)))==-1)
  126.             {perror("bind error\n");}
  127. else printf("bind ok\n");
  128.      listen(sock,128);
  129.              return sock;
  130. }
  131. #include<server.h>
  132. int main()
  133. {
  134. server_start();
  135. return 0;
  136. }
复制代码


单历程服务端只符合简易情况下的需求。
单历程接纳非阻塞瓜代执行的策略让等待毗连和读取处理瓜代执行,但是如果服务器长时间为某个客户端处理业务,导致无法建立新毗连处理其他人的数据。
并发服务器-多历程服务器

多历程服务器是具备并发处理本领的服务器模子,可以并发毗连并发处理,为若干客户端提供服务。并发数目取决于历程数目,频繁创建和烧毁历程有庞大的体系开销。
多历程模子中有多个处理单元,为多对多模子。多历程模子中,子历程随客户端持续,链接乐成创建,客户端退出则子历程退出。僵尸历程接纳,无论是阻塞接纳还是非阻塞,都会影响毗连,所以我们让线程负责接纳。

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<sys/types.h>
  4. #include<sys/stat.h>
  5. #include<time.h>
  6. #include<string.h>
  7. #include<arpa/inet.h>
  8. #include<sys/socket.h>
  9. #include<fcntl.h>
  10. #include<sys/types.h>
  11. #include<sys/stat.h>
  12. #include<errno.h>
  13. #include<pthread.h>
  14. #include<signal.h>
  15. #include<sys/wait.h>
  16. int init_net();
  17. void mess_response(int,struct sockaddr_in);
  18. int recv_request(int);
  19. int start_server();
  20. void* thread_wait(void* arg);
  21. void sig_wait(int n);
  22. #include<server.h>
  23. int init_net()
  24. {
  25. int sock;
  26. struct sockaddr_in sockaddr;
  27. bzero(&sockaddr,sizeof(sockaddr));
  28. sockaddr.sin_family=AF_INET;
  29. sockaddr.sin_port=htons(1234);
  30. sockaddr.sin_addr.s_addr=htonl(INADDR_ANY);
  31. if((sock=socket(AF_INET,SOCK_STREAM,0))==-1)
  32. printf("socket error\n");
  33. else printf("socket ok\n");
  34. if((bind(sock,(struct sockaddr*)&sockaddr,sizeof(sockaddr)))==-1)
  35.             {perror("bind error\n");}
  36. else printf("bind ok\n");
  37.      listen(sock,128);
  38.              return sock;
  39. }
  40. #include<server.h>
  41. void mess_response(int so,struct sockaddr_in addr)
  42. {
  43.         char s[1024];
  44.         char c[16];
  45.         bzero(c,16);
  46.         bzero(s,1024);
  47.         inet_ntop(AF_INET,&addr.sin_addr,c,16);
  48.          sprintf(s,"hi %s\n",c);
  49.           int t=send(so,s,strlen(s),MSG_NOSIGNAL);
  50.           if(t<0)perror("err");
  51.           return;
  52. }
  53. #include<server.h>
  54. int recv_request(int sock)
  55. {
  56.         char s[1024];
  57.         char tim[1024];
  58.         bzero(s,sizeof(s));
  59.         bzero(tim,sizeof(tim));
  60.         int len;
  61.         time_t tp;
  62.         while((len=recv(sock,s,sizeof(s),0))>0)
  63.         {
  64.         s[strlen(s)-1]='\0';
  65.         if(strncmp(s,"time",strlen(s))==0)
  66.         {
  67.                 tp=time(NULL);
  68.                 ctime_r(&tp,tim);
  69.                 send(sock,tim,strlen(tim),MSG_NOSIGNAL);
  70.         }
  71.         else{
  72.                 send(sock,"try again",9,MSG_NOSIGNAL);
  73.         }
  74.         bzero(s,sizeof(s));
  75.         bzero(tim,sizeof(tim));
  76.         }
  77.                 printf("client sock %d  ,child process %d its exiting...\n",sock,getpid());
  78.                 close(sock);
  79.                 exit(sock);
  80. return 0;
  81. }
  82. #include<server.h>
  83. void sig_wait(int n)
  84. {
  85. pid_t zpid;
  86. while((zpid=waitpid(-1,NULL,WNOHANG))!=-1)
  87. {
  88. if(zpid>0){
  89. printf("thread wait success,zpid %d\n",zpid);
  90. }
  91. }}
  92. #include<server.h>
  93. void* thread_wait(void* arg)
  94. {
  95. struct sigaction act,oact;
  96. pthread_detach(pthread_self());
  97. act.sa_handler=sig_wait;
  98. act.sa_flags=0;
  99. sigemptyset(&act.sa_mask);
  100. sigaction(SIGCHLD,&act,&oact);
  101. sigprocmask(SIG_SETMASK,&act.sa_mask,NULL);
  102. printf("wait thread 0x%x waiting..\n",(unsigned int)pthread_self());
  103. while(1)
  104. sleep(1);
  105. pthread_exit(NULL);
  106. }
  107. #include<server.h>
  108. int server_start()
  109. {
  110.         int sock,csock;
  111.         struct sockaddr_in sock_client;
  112.         int i;
  113.         bzero(&sock_client,sizeof(sock_client));
  114.         sock=init_net();
  115.         printf("init ok\n");
  116.         socklen_t socklen;
  117.         sigset_t set,oset;
  118.         sigemptyset(&set);
  119.         sigaddset(&set,SIGCHLD);
  120.         sigprocmask(SIG_SETMASK,&set,&oset);
  121.         pthread_t tid;
  122.         int err;
  123.         if((err=pthread_create(&tid,NULL,thread_wait,NULL))>0){
  124.         printf("wait thread create err:%s\n",strerror(err));
  125.         exit(0);
  126.         }
  127.         pid_t pid;
  128.         while(1)
  129.         {
  130.         socklen=sizeof(sock_client);
  131.         if(( csock=(accept(sock,(struct sockaddr*)&sock_client,&socklen)))>0)
  132.         {
  133.             pid=fork();
  134.             if(pid>0)
  135.            {
  136.           mess_response(csock,sock_client);
  137.            printf("accept success\n");
  138.          }
  139.            else if(pid==0)
  140.         {
  141.         recv_request(csock);
  142.         }
  143.         else exit(0);
  144.         }
  145.         else {
  146.         printf("accept error\n");
  147.                 }
  148.        }
  149.         close(sock);
  150.         return 0;
  151. }
  152. #include<server.h>
  153. int main()
  154. {
  155. server_start();
  156. return 0;
  157. }
复制代码

多历程稳定性强,因为每个处理单元是一个历程,一个历程异常退出不会影响其他历程。
并发服务器-多线程服务器

稳定性较差,线程瓦解可能影响其他线程,但是开销小轻量级。(线程安全问题)
并发量取决于线程数目。
频繁创建烧毁历程有庞大的体系开销。
和多历程差不多。
多路IO复用服务器

IO复用技术又名多路IO转接技术,可以帮助开发者监听大量的sock。
sock监听技术,io监听技术。
select模子

写的是单历程的。

#include<sys/select.h>//头文件
fd_set set;//监听集合类型
FD_ZERO(&set);//初始化监听集合,将位码初始化为0
FD_SET(int sockfd,&set);//将sockfd在集合中对应的位设置成1
FD_CLR(int sockfd,&sest);//将sockfd在集合中的对应位设置为0
int code=FD_ISSET(int sock,&set);//返回sockfd在集合中位码
int ready=select(maxfd+1,fd_set* rd,fd_set* wr,fd_set* err,timeval* timeout);//监听函数,监听事件选择以集合为单位,批处理,timeout=NULL,阻塞监听,监听集合对应文件描述符表,所以在设置监听数目时要考虑设备描述符。
struct timeval* val;   val.secons=0; val.ms=0;//如果要非阻塞使用select,需要定义时间结构体并将时间成员初始化成0,如果需要select定时阻塞,用户自行设置时间在结构体中。
  1. #include<unistd.h>
  2. #include<stdlib.h>
  3. #include<signal.h>
  4. #include<time.h>
  5. #include<sys/select.h>
  6. #include<sys/socket.h>
  7. #include<string.h>
  8. #include<arpa/inet.h>
  9. int main()
  10. {
  11.         //sock的就绪数量
  12.         int socknum;
  13.         //存储客户端sock
  14.         int sockarry[1020];
  15.         //最大的描述符
  16.         int maxfd;
  17.         int ssock;
  18.         int csock;
  19.         //初始化客户端sock数组
  20.         int i;
  21.         for(i=0;i<1020;i++)
  22.         {
  23.         sockarry[i]=-1;
  24.         }
  25.         //初始化网络
  26.         struct sockaddr_in saddr,caddr;
  27.         saddr.sin_family=AF_INET;
  28.         saddr.sin_port=htons(1234);
  29.         saddr.sin_addr.s_addr=htonl(INADDR_ANY);
  30.         if((ssock=socket(AF_INET,SOCK_STREAM,0))==-1)
  31.         {
  32.         perror("sock init error\n");
  33.         }
  34.         bind(ssock,(struct sockaddr*)&saddr,sizeof(saddr));
  35.         listen(ssock,128);
  36.         maxfd=ssock;
  37.         //监听集合
  38.         fd_set set,oset;
  39.         //初始化监听集合
  40.         FD_ZERO(&set);
  41.         FD_SET(ssock,&set);
  42.         socklen_t addrlen;
  43.         //初次连接回复
  44.         char response[1500];
  45.         char cip[16];
  46.         char buff[1024];
  47.         bzero(response,1500);
  48.         bzero(cip,16);
  49.         bzero(buff,1024);
  50.         //时间
  51.         char timebuff[1024];
  52.         time_t tp;
  53.         int len;
  54.         printf("server running\n");
  55.         //轮询监听
  56.         while(1)
  57.         {
  58.         oset=set;
  59.         if((socknum=select(maxfd+1,&oset,NULL,NULL,NULL))==-1)
  60.         perror("select() failed");
  61.     while(socknum)
  62.         {
  63.         //是severfd
  64.         if(FD_ISSET(ssock,&oset))
  65.         {
  66.         addrlen=sizeof(caddr);
  67.         csock=accept(ssock,(struct sockaddr*)&caddr,&addrlen);
  68.         //首次连接成功返回信息
  69.         inet_ntop(AF_INET,&caddr.sin_addr.s_addr,cip,16);
  70.         sprintf(response,"hi %s",cip);
  71.         send(csock,response,strlen(response),MSG_NOSIGNAL);
  72.         bzero(response,sizeof(response));
  73.         //设置监听,存入数组
  74.         FD_SET(csock,&set);
  75.         for( i=0;i<1020;i++)
  76.         {
  77.         if(sockarry[i]==-1)
  78.         {
  79.         sockarry[i]=csock;
  80.         break;
  81.         }
  82.         }
  83.         //更新最大sockfd
  84.         if(maxfd<csock)maxfd=csock;
  85.         //将oset设置为0
  86.         FD_CLR(ssock,&oset);
  87.         }
  88.         //是clientfd
  89.         else
  90.         {
  91.         i=0;
  92.         //遍历sockarry数组,查找就绪的csock并处理
  93.         for(i;i<1020;i++)
  94.         {
  95.         if(sockarry[i]!=-1)
  96.         if(FD_ISSET(sockarry[i],&oset))
  97.         {
  98.         //读取处理数组
  99.         if((len=recv(sockarry[i],buff,sizeof(buff),0))>0)
  100.         {
  101.         buff[strlen(buff)-1]='\0';
  102.         if((strcmp(buff,"time"))==0)
  103.         {
  104.         bzero(timebuff,1024);
  105.         tp=time(NULL);
  106.         ctime_r(&tp,timebuff);
  107.         send(sockarry[i],timebuff,strlen(timebuff),MSG_NOSIGNAL);
  108.         }
  109.         else{
  110.         send(sockarry[i],"try again",10,MSG_NOSIGNAL);
  111.         }
  112.         bzero(buff,1024);
  113.         FD_CLR(sockarry[i],&oset);
  114.         }
  115.         if(len==0)
  116.         {
  117.         //客户端退出,在监听中删除,在组中删除
  118.         FD_CLR(sockarry[i],&set);
  119.         FD_CLR(sockarry[i],&oset);
  120.         close(sockarry[i]);
  121.         sockarry[i]=-1;
  122.         }
  123.         break;
  124.         }
  125.         }
  126.         }
  127.         socknum--;
  128.         }
  129.         }
  130.         close(ssock);
  131.         return 0;
  132. }
复制代码
长处:
1.使用比力简单,相识监听集合以及IO复用机制即可使用,帮助用户完成少量sock的网络事件监听
2.跨平台兼容性比力好,在各个体系语言均有select支持
3.select支持微妙级定时,可以满意一些特定需求
缺点:
1.select无法满意大监听需求,最大监听数1024
2.轮询监听,随着轮询数目的增大,io处理性能呈线性下降
3.select监听到停当后只返回停当的数目,需要用户自行遍历查找停当的sock
4.需要用户举行传入传出分离设置
5.随着select的持续使用,会有庞大的开销和挂载开销
6.监听数目比力少,其次设置监听不机动,无法针对不同的sock设置不同的监听
poll模子

长处:
1.监听事件的种类丰富,对监听与停当举行了传入传出分离,无需用户分离
2.poll支持用户自定义长度结构体数组作为集合,突破了1024限定(轮询)
缺点:
1.轮询问题
2.拷贝开销挂载开销
3.只返回停当需要用户自行遍历查找停当的sock
4.只支持毫秒级别定时
5.在某些特定的Linux版本才可以使用
struct pollfd listen_array[4096];//监听数组,还可以帮助用户存储sock
listen_array[0].fd=sock;//如果需要监听则设置为某个sock,取消监听设置为-1
listen_arry[0].events=POLLIN|POLLOUT|POLLERR;//设置要监听的事件
listen_arry[0],revents;//如果监听的sock停当,体系将停当事件传到revents中
int readycode=poll(listen_array);//timeout -1阻塞 0非阻塞 >0定时阻塞
  1. #include<stdio.h>
  2. #include<unistd.h>
  3. #include<stdlib.h>
  4. #include<signal.h>
  5. #include<time.h>
  6. #include<sys/select.h>
  7. #include<sys/socket.h>
  8. #include<poll.h>
  9. #include<string.h>
  10. #include<arpa/inet.h>
  11. int main()
  12. {
  13.         //sock的就绪数量
  14.         int socknum;
  15.         //存储客户端sock
  16.         struct pollfd sockarry[4096];
  17.         int ssock;
  18.         int csock;
  19.         //初始化客户端sock数组
  20.         int i;
  21.         for(i=0;i<4096;i++)
  22.         {
  23.         sockarry[i].fd=-1;
  24.         sockarry[i].events=POLLIN;
  25.         }
  26.         //初始化网络
  27.         struct sockaddr_in saddr,caddr;
  28.         saddr.sin_family=AF_INET;
  29.         saddr.sin_port=htons(1234);
  30.         saddr.sin_addr.s_addr=htonl(INADDR_ANY);
  31.         if((ssock=socket(AF_INET,SOCK_STREAM,0))==-1)
  32.         {
  33.         perror("sock init error\n");
  34.         }
  35.         bind(ssock,(struct sockaddr*)&saddr,sizeof(saddr));
  36.         listen(ssock,128);
  37.          //监听集合
  38.         sockarry[0].fd=ssock;
  39.         socklen_t addrlen;
  40.         //初次连接回复
  41.         char response[1500];
  42.         char cip[16];
  43.         char buff[1024];
  44.         bzero(response,1500);
  45.         bzero(cip,16);
  46.         bzero(buff,1024);
  47.         //时间
  48.         char timebuff[1024];
  49.         time_t tp;
  50.         int len;
  51.         printf("server running\n");
  52.         //轮询监听
  53.         while(1)
  54.         {
  55.         if((socknum=poll(sockarry,4096,-1))==-1)
  56.         perror("poll() failed");
  57.         while(socknum)
  58.         {
  59.         //是severfd
  60.         if(sockarry[0].revents==POLLIN)
  61.         {
  62.         addrlen=sizeof(caddr);
  63.         csock=accept(ssock,(struct sockaddr*)&caddr,&addrlen);
  64.         //首次连接成功返回信息
  65.         inet_ntop(AF_INET,&caddr.sin_addr.s_addr,cip,16);
  66.         sprintf(response,"hi %s",cip);
  67.         send(csock,response,strlen(response),MSG_NOSIGNAL);
  68.         bzero(response,sizeof(response));
  69.         //设置监听,存入数组
  70.         for( i=1;i<4096;i++)
  71.         {
  72.         if(sockarry[i].fd==-1)
  73.         {
  74.         sockarry[i].fd=csock;
  75.         break;
  76.         }
  77.         }
  78.         //就绪处理
  79.         sockarry[0].revents=0;
  80.         }
  81.         //是clientfd
  82.         else
  83.         {
  84.         i=1;
  85.         //遍历sockarry数组,查找就绪的csock并处理
  86.         for(i;i<4096;i++)
  87.         {
  88.         if(sockarry[i].fd!=-1)
  89.         if(sockarry[i].revents==POLLIN)
  90.         {
  91.         //读取处理数组
  92.         if((len=recv(sockarry[i].fd,buff,sizeof(buff),0))>0)
  93.         {
  94.         buff[strlen(buff)-1]='\0';
  95.         if((strcmp(buff,"time"))==0)
  96.         {
  97.         bzero(timebuff,1024);
  98.         tp=time(NULL);
  99.         ctime_r(&tp,timebuff);
  100.         send(sockarry[i].fd,timebuff,strlen(timebuff),MSG_NOSIGNAL);
  101.         }
  102.          else{
  103.         send(sockarry[i].fd,"try again",10,MSG_NOSIGNAL);
  104.         }
  105.         bzero(buff,1024);
  106.         sockarry[i].revents=0;
  107.         }
  108.         if(len==0)
  109.         {
  110.         //客户端退出,在监听中删除,在组中删除
  111.         close(sockarry[i].fd);
  112.         sockarry[i].fd=-1;
  113.         sockarry[i].revents=0;
  114.         }
  115.         break;
  116.         }
  117.         }
  118.         }
  119.         socknum--;
  120.         }
  121.         }
  122.         close(ssock);
  123.         return 0;
  124. }
复制代码
用ulimit -a检察一下,如果小于4096,那么创建的sockarray会报错。

epoll模子

整合了select和poll的优势,而且优化了问题
epoll使用红黑树作为监听集合(监听树)
int epfd=epoll_create(int treeMax);//创建监听树,参数为巨细,返回值指向树的描述符
struct epolevent node;
node.data.fd=sock;
node.events=EPOLLIN|EPOLLOUT|EPOLLERR;
epoll_ctl(epfd,EPOLL_CTL_ADD,sock,struct epollevent* node);//添加节点
epoll_ctl(epfd,EPOLL_CTL_DEL,sock,NULL);//删除节点
epoll_ctl(epfd,EPOLL_CTL_MOD,sock,&node);//修改只能监听的事件,无法修改sock
struct epollevent ready_arry[Max];//用户空间定义停当队列(数组)
int readynode=epoll_wait(epfd,ready_arry,Max,-1);//Max停当最大数,树巨细=停当队列巨细=最大停当数
epoll监听树直接创建于内核,然后节点放入epoll等待队列,然后停当后弹出到停当链表(双向链表结构体,内核),然后从内核空间拷贝到用户空间,然后epoll监听到停当直接返回停当节点(sock),用户遍历处理这些sock即可。
epoll不用担心轮询问题,所以没有监听限定,可以监听体系最大描述符数目,并没有多余开销
epoll不存在轮询问题,无需担心监听数目增大,体系开销增大。
epoll直接返回停当的sock,用户直接处理即可。
epoll监听集合在内核层,所以不会出现重复拷贝和重复挂载的问题,包管每个节点只拷贝一次,只挂载一次。
epoll与poll一样,监听的事件更丰富,而后设置监听比力机动,可以对不同的sock设置不同的事件监听。
作为监听模子,select,poll,epoll,epoll监听本领最强,但是处理本领而言(与监听模子无关)
监听部门(通过io复用技术监听管理有效毗连)
处理部门(并发处理),又快又好的将请叱责部处理掉(快速反应,进步体验)
epoll的监听模式(水平触发模式EPOLLLT 边沿触发模式EPOLLET)EPOLLONTSHOT
epoll是线程安全的,epoll_ctl函数内部自带互斥锁,所以一个线程在访问修改树节点时,其他线程无法挂起等待
EPOLL+线程池服务器(满意高并发需求)

线程池技术:
预创建原则,线程池内部预备线程备用,不宜过多
线程应该重用性,可以一对多处理使命或服务不同的客户端
处理单元(线程)数目并不固定,动态扩容与缩减(使命量)
计划机动的使命通报方式与使命接口,线程可以执行不同种类的使命,不能将线程工作固定
线程池技术多为线程容器
thread_poll_create(int max,int min,int qmax);
int thread_producer_add(pool_t* pt,business_t bs);//添加一次业务向队列(生产者)
void* thread_customer(void* arg);//消耗者线程使命,等待队列,循环获取业务并执行
void* thread_manager(void* arg);//检察线程池阈值,动态扩容缩减线程
int net_init();//服务器网络初始化
int first_response();//毗连乐成初次响应
int epoll_init();//epoll创建初始化
int epoll_listen();//主线程循环监听sock事件,并根据停当添加使命
void* accept_business(void* arg);//tcp毗连业务
void* response_business(voiod* arg);//响应处理业务
if_thread_alive(pthread_t tid);//测试线程,返回0表现线程失效,1表现有效
  1. #include<string.h>
  2. #include<stdio.h>
  3. #include<unistd.h>
  4. #include<stdlib.h>
  5. #include<sys/stat.h>
  6. #include<sys/types.h>
  7. #include<fcntl.h>
  8. #include<sys/socket.h>
  9. #include<arpa/inet.h>
  10. #include<pthread.h>
  11. #include<sys/epoll.h>
  12. #include<time.h>
  13. #include<signal.h>
  14. #include<errno.h>
  15. #define EPOLL_MAX 190000
  16. int epfd;//监听树的描述符
  17. //business_t业务类型
  18. typedef struct
  19. {
  20. void* (*task)(void* arg);
  21. void* arg;
  22. }business_t;
  23. //pool_t线程池类型
  24. typedef struct
  25. {
  26. //线程池开关
  27. int thread_shutdown;
  28. //线程池最大线程数
  29. int thread_max;
  30. //线程池最小线程数
  31. int thread_min;
  32. //存活有效的线程数量
  33. int thread_alive;
  34. //繁忙线程数量
  35. int thread_busy;
  36. //缩减码
  37. int exit_code;
  38. //环形任务队列
  39. business_t* queue;
  40. int front;
  41. int rear;
  42. int max;
  43. int cur;
  44. //互斥锁
  45. pthread_mutex_t lock;
  46. //生产者条件变量
  47. pthread_cond_t Not_Full;
  48. //消费者条件变量
  49. pthread_cond_t Not_Empty;
  50. //消费者tid数组
  51. pthread_t* ctids;
  52. //管理者线程io
  53. pthread_t mtid;
  54. }pool_t;
  55. pool_t* thread_pool_create(int tmax,int tmin,int qmax);
  56. int thread_producer_add(pool_t* pt,business_t bs);
  57. void* thread_customer(void* arg);
  58. int if_thread_alive(pthread_t tid);
  59. void* thread_mananger(void* arg);
  60. int net_init(void);
  61. int first_response(int sock,struct sockaddr_in caddr);
  62. int epoll_init(int sock);
  63. int epoll_listen(pool_t* pt,int sock);
  64. void* accept_business(void*);
  65. void* recv_business(void*);
  66. #include<pool.h>
  67. void* accept_business(void* arg)
  68. {
  69.         int sock=*(int*)arg;
  70.         int csock;
  71.         struct sockaddr_in caddr;
  72.         char buffer[16];
  73.         bzero(buffer,sizeof(buffer));
  74.         socklen_t addrlen=sizeof(caddr);
  75.         if((csock=accept(sock,(struct sockaddr*)&caddr,&addrlen))==-1)
  76.                 perror("accept_business,accept failed");
  77.         first_response(csock,caddr);
  78.         //设置监听
  79.         struct epoll_event node;
  80.         node.data.fd=csock;
  81.         node.events=EPOLLIN|EPOLLET;
  82.         epoll_ctl(epfd,EPOLL_CTL_ADD,csock,&node);
  83.         inet_ntop(AF_INET,&caddr.sin_addr.s_addr,buffer,16);
  84.         printf("customer 0x%x execl accept_business success,client ip %s,client port %d\n",(unsigned int)pthread_self(),buffer,ntohs(caddr.sin_port));
  85.         return NULL;
  86. }
  87.     #include<pool.h>
  88.     int if_thread_alive(pthread_t tid)
  89.     {
  90.     int err;
  91.     err=pthread_kill(tid,0);
  92.     if(err==ESRCH)
  93.     return 0;
  94.     else return 1;
  95.     }
  96. #include<pool.h>
  97. void* recv_business(void* arg)
  98. {
  99.         int sock=*(int*)arg;
  100.         //读取请求数据,使用非阻塞,当前缓冲区无可读数据立即返回
  101.         char buffer[1024];
  102.         char timebuf[1024];
  103.         time_t tp;
  104.         int recvlen;
  105.         bzero(buffer,sizeof(buffer));
  106.         while((recvlen=recv(sock,buffer,sizeof(buffer),MSG_DONTWAIT))>0)
  107.         {
  108.                 //检测关键字,处理请求
  109.                 buffer[strlen(buffer)-1]='\0';
  110.                 if((strcmp(buffer,"time"))==0){
  111.                         bzero(timebuf,1024);
  112.                         tp=time(NULL);
  113.                         ctime_r(&tp,timebuf);
  114.                         send(sock,timebuf,strlen(timebuf),MSG_NOSIGNAL);
  115.                         printf("recv_business execl success,response time\n");
  116.                 }
  117.                 else{
  118.                         send(sock,"Please try again",17,MSG_NOSIGNAL);
  119.                         printf("customer 0x%x recv_business execl success,reponse tryagain\n",(unsigned int)pthread_self());
  120.                 }
  121.         }
  122.         if(recvlen==0){
  123.                 //删除监听
  124.                 epoll_ctl(epfd,EPOLL_CTL_DEL,sock,NULL);
  125.                 printf("client %d exit,close csock\n",sock);
  126.                 close(sock);
  127.                 printf("customer 0x%xrecv_business execl success, client exit\n",(unsigned int)pthread_self());
  128.         }
  129.         if(recvlen==-1){
  130.                 if(errno==EAGAIN){
  131.                         //非阻塞返回
  132.                 }
  133.                 else perror("recv_bussiness recv call fialed");
  134.         }
  135. return NULL;
  136. }
  137. #include<pool.h>
  138. extern int epfd;
  139. int epoll_init(int sock)
  140. {
  141. if((epfd=epoll_create(EPOLL_MAX))==-1)
  142. perror("create failed");
  143. struct epoll_event node;
  144. node.data.fd=sock;
  145. node.events=EPOLLIN|EPOLLET;
  146. epoll_ctl(epfd,EPOLL_CTL_ADD,sock,&node);
  147. //创建监听树并将seversock设置成监听读事件
  148. printf("server epoll success\n");
  149. return 0;
  150. }
  151. #include<pool.h>
  152. void* thread_customer(void* arg)
  153. {
  154.         //接收参数
  155.         pool_t* pt=(pool_t*)arg;
  156.         business_t bs;
  157.         pthread_detach(pthread_self());
  158.         //循环等待任务并处理
  159.         printf("customer thread 0x%x,wait business\n",(unsigned int)pthread_self());
  160.         while(pt->thread_shutdown)
  161.         {
  162.                 pthread_mutex_lock(&pt->lock);
  163.                 while(pt->cur==0)
  164.                 {
  165.                         pthread_cond_wait(&pt->Not_Empty,&pt->lock);
  166.                         if(!pt->thread_shutdown){
  167.                                 printf("customer 0x%x,thread_shutdown %d,customer exiting..\n",(unsigned int)pthread_self(),pt->thread_shutdown);
  168.                                 pthread_mutex_unlock(&pt->lock);
  169.                                 pthread_exit(NULL);
  170.                         }
  171.                         if(pt->exit_code>0){
  172.                                 printf("manager kill customer 0x%x success\n",(unsigned int)pthread_self());
  173.                                 --(pt->thread_alive);
  174.                                 --(pt->exit_code);
  175.                                 pthread_mutex_unlock(&pt->lock);
  176.                                 pthread_exit(NULL);
  177.                         }
  178.                 }
  179.                 //获取任务
  180.                 bs.task=pt->queue[pt->rear].task;
  181.                 bs.arg=pt->queue[pt->rear].arg;
  182.                 --(pt->cur);
  183.                 pt->rear=(pt->rear+1)%pt->max;
  184.                 ++(pt->thread_busy);
  185.                 pthread_mutex_unlock(&pt->lock);
  186.                 //唤醒生产者
  187.                 pthread_cond_signal(&pt->Not_Full);
  188.                 //执行任务
  189.                 bs.task(bs.arg);
  190.                 pthread_mutex_lock(&pt->lock);
  191.                 --(pt->thread_busy);
  192.                 pthread_mutex_unlock(&pt->lock);
  193.         }
  194.         printf("customer 0x%x,thread_shutdown %d,customer exiting..\n",(unsigned int)pthread_self(),pt->thread_shutdown);
  195.         pthread_exit(NULL);
  196. }
  197. #include<pool.h>
  198. void* thread_mananger(void* arg)
  199. {
  200.         pool_t* pt=(pool_t*)arg;
  201.         int alive,busy,cur;
  202.         int flag;
  203.         int add;
  204.         int fd;
  205.         if((access("manager_information",F_OK))==0)
  206.                 unlink("manager_information");
  207.         fd=open("manager_information",O_RDWR|O_CREAT,0664);
  208.         char result[4096];
  209.         while(pt->thread_shutdown){
  210.                 pthread_mutex_lock(&pt->lock);
  211.                 alive=pt->thread_alive;
  212.                 busy=pt->thread_busy;
  213.                 cur=pt->cur;
  214.                 pthread_mutex_unlock(&pt->lock);
  215.                 bzero(result,sizeof(result));
  216.                 sprintf(result,"manager 0x%x,alive %d ,busy %d,idel %d busy/alive %.2f%% alive/max %.2f%%\n",alive,busy,alive-busy,(double)busy/alive*100,(double)alive/pt->thread_max*100);
  217.                 write(fd,result,strlen(result));
  218.                 //扩容 thread_min作为扩容与缩减量
  219.                 //1.任务数量cur>=alive-busy
  220.                 //2.使用百分比扩容,如果忙线程占存活线程的70%
  221.                 //3.扩容不能超出最大阈值thread_max
  222.                 int err;
  223.                 if((cur>=alive-busy||(double)busy/alive*100>=70)&&alive+pt->thread_min<=pt->thread_max)
  224.                 {
  225.                         //ctids,如果为0直接使用,非0要测试线程是否存活
  226.                         //遍历tids查找可用位置,并且创建新消费者
  227.                         for(flag=0,add=0;flag<pt->thread_max&&add<pt->thread_min;flag++)
  228.                         {
  229.                                 if(pt->ctids[flag]==0||!if_thread_alive(pt->ctids[flag]))
  230.                                 {
  231.                                         if((err=pthread_create(&pt->ctids[flag],NULL,thread_customer,(void*)pt))>0)
  232.                                                 printf("manager create new customer failed:%s\n",strerror(err));
  233.                                         add++;
  234.                                         pthread_mutex_lock(&pt->lock);
  235.                                         ++(pt->thread_alive);
  236.                                         pthread_mutex_unlock(&pt->lock);
  237.                                  }
  238.                         }
  239.                 }
  240.                 //缩减条件:闲线程是忙线程的倍数,缩减不允许小于最小阈值
  241.                 if(busy*2<=alive-busy&&alive-pt->thread_min>=pt->thread_min)
  242.                 {
  243.                         //如何缩减
  244.                         //1.管理者缩减cance,改造ctids,除了存储tid,还要存储记录线程状态,管理者遍历而后cancel取消闲线程
  245.                         //2.配合缩减,消费者退出码,唤醒闲消费者,消费者检查退出码,而后自行退出
  246.                         pt->exit_code=pt->thread_min;
  247.                         int i;
  248.                         for(i=0;i<pt->thread_min;i++)
  249.                                 pthread_cond_signal(&pt->Not_Empty);
  250.                 }
  251.                 sleep(1);
  252.         }
  253.         printf("manager 0x%x exit.\n",(unsigned int)pthread_self());
  254.         pthread_exit(NULL);
  255. }
  256. #include<pool.h>
  257. //生产者监听模型
  258. int epoll_listen(pool_t* pt,int sock)
  259. {
  260.         int readycode;
  261.         struct epoll_event readyarray[EPOLL_MAX];
  262.         int i;
  263.         business_t bs;
  264.         while(pt->thread_shutdown)
  265.         {
  266.                 if((readycode=epoll_wait(epfd,readyarray,EPOLL_MAX,-1))==-1)
  267.                         perror("epoll_listen,epoll_wait call failed");
  268.                 else{
  269.                         i=0;
  270.                         while(readycode)
  271.                         {
  272.                                 //判断就绪
  273.                                 if(readyarray[i].data.fd==sock){
  274.                                         //serversock ready
  275.                                         bs.task=accept_business;
  276.                                         bs.arg=(void*)&readyarray[i].data.fd;
  277.                                         thread_producer_add(pt,bs);
  278.                                         printf("thread producer 0x%x add accept business..\n",(unsigned int)pthread_self());
  279.                                 }
  280.                                 else{
  281.                                         //clientsock ready
  282.                                         bs.task=recv_business;
  283.                                         bs.arg=(void*)&readyarray[i].data.fd;
  284.                                         thread_producer_add(pt,bs);
  285.                                         printf("thrad producer 0x%x add recv business..\n",(unsigned int)pthread_self());
  286.                                 }
  287.                                 --readycode;
  288.                                 ++i;
  289.                         }}
  290.         }
  291.         printf("producer is done..\n");
  292.         return 0;
  293. }
  294. #include<pool.h>
  295. pool_t* thread_pool_create(int tmax,int tmin,int qmax)
  296. {
  297.         //对线程池类初始化,申请空间,按最小阈值创建消费者并创建管理者
  298.         pool_t* pt=NULL;
  299.         if((pt=malloc(sizeof(pool_t)))==NULL)
  300.                 perror("thread_pool_create,malloc pool failed");
  301.         pt->thread_shutdown=1;
  302.         pt->thread_max=tmax;
  303.         pt->thread_min=tmin;
  304.         pt->thread_alive=0;
  305.         pt->thread_busy=0;
  306.         pt->exit_code=0;
  307.         //创建队列
  308.         if((pt->queue=malloc(sizeof(business_t)*qmax))==NULL)
  309.                 perror("thread_pool_crreate,malloc queue failed");
  310.         pt->front=0;
  311.         pt->rear=0;
  312.         pt->max=qmax;
  313.         pt->cur=0;
  314.         if((pt->ctids=malloc(sizeof(pthread_t)*tmax))==NULL)
  315.                 perror("thread_pool_create,malloc ctids failed");
  316.         //初始化ctids,0
  317.         bzero(pt->ctids,sizeof(pthread_t)*tmax);
  318.         if(pthread_mutex_init(&(pt->lock),NULL)!=0||pthread_cond_init(&(pt->Not_Full),NULL)!=0||pthread_cond_init(&(pt->Not_Empty),NULL)!=0){
  319.                 printf("thread_pool_create,init lock or cond failed\n");
  320.         }
  321.         //预创建消费者
  322.         int err;
  323.         int i;
  324.         for(i=0;i<tmin;i++){
  325.                 if((err=pthread_create(&pt->ctids[i],NULL,thread_customer,pt))>0)
  326.                         printf("thread_pool_create,create customer failed:%s\n",strerror(err));
  327.                 else ++(pt->thread_alive);
  328.         }
  329.         //管理线程
  330.         if((err=pthread_create(&pt->mtid,NULL,thread_mananger,pt))>0)
  331.                 printf("thread_pool_create,cretate mannager failed:%s\n",strerror(err));
  332.         return pt;
  333. }
  334. #include<pool.h>
  335. int first_response(int sock,struct sockaddr_in caddr)
  336. {
  337. char cip[16];
  338. char response[1500];
  339. bzero(cip,16);
  340. bzero(response,sizeof(response));
  341. inet_ntop(AF_INET,&caddr.sin_addr,cip,16);
  342. sprintf(response,"hi,%s connection server host  success\n",cip);
  343. if((send(sock,response,strlen(response),0))==-1)
  344. perror("first_response,send failed");
  345. return 0;
  346. }
  347. #include<pool.h>
  348. int net_init(void)
  349. {
  350. int sock;
  351. struct sockaddr_in saddr;
  352. bzero(&saddr,sizeof(saddr));
  353. saddr.sin_family=AF_INET;
  354. saddr.sin_port=htons(1234);
  355. saddr.sin_addr.s_addr=htonl(INADDR_ANY);
  356. if((sock=socket(AF_INET,SOCK_STREAM,0))==-1)
  357. perror("sock failed");
  358. if((bind(sock,(struct sockaddr*)&saddr,sizeof(saddr)))==-1)
  359. perror("bind failed");
  360. if((listen(sock,128))==-1)
  361. perror("listen failed");
  362. printf("srver init success\n");
  363. return sock;
  364. }
  365. #include<pool.h>
  366. int thread_producer_add(pool_t* pt,business_t bs)
  367. {
  368.         //生产者任务
  369.         pthread_mutex_lock(&pt->lock);
  370.         if(pt->thread_shutdown)
  371.         {
  372.                 while(pt->cur==pt->max)
  373.                 {
  374.                         pthread_cond_wait(&pt->Not_Full,&pt->lock);
  375.                         if(!pt->thread_shutdown){
  376.                                 printf("cusomter thread 0x%x,shutdown %d,thread exit..\n",(unsigned int)pthread_self(),pt->thread_shutdown);
  377.                                 pthread_mutex_unlock(&pt->lock);
  378.                                 pthread_exit(NULL);
  379.                         }
  380.                 }
  381.                 //添加一次业务
  382.                 pt->queue[pt->front].task=bs.task;
  383.                 pt->queue[pt->front].arg=bs.arg;
  384.                 ++(pt->cur);
  385.                 pt->front=(pt->front+1)%pt->max;
  386.                 pthread_mutex_unlock(&pt->lock);
  387.                 pthread_cond_signal(&pt->Not_Empty);
  388. }
  389. pthread_mutex_unlock(&pt->lock);
  390. return 0;
  391. }
  392. #include<pool.h>
  393. int main()
  394. {
  395.         int serverfd=net_init();
  396.         epoll_init(serverfd);
  397.         pool_t* pt=thread_pool_create(100,10,1000);
  398.         epoll_listen(pt,serverfd);
  399.         return 0;
  400. }
复制代码



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

火影

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表