select的限制

select的并发数受到两个限制:1.一个进程能打开的最大描述符数量;2.select中fd_set集合容量的限制(FD_SETSIZE)

关于进程的最大描述符数量:

ulimit -n:查看一个进程能打开的最大描述符数量

ulimit -n 2048:将最大描述符数量更改为2048,其它数量也可以,需root权限

  1. //最大描述符测试,如果数量是1024的情况下,不出意外程序会在i=1021时达到最大值,因为0,1,2被标准输入输出占有
  2. int main(int argc,char *argv[]){
  3. int i=0;
  4. while(1){
  5. int sockfd;
  6. struct sockaddr_in servaddr;
  7. char buf[1024];
  8. if((sockfd=socket(PF_INET,SOCK_STREAM,0)) < 0){
  9. printf("%d\n",i);
  10. err_quit("socket");
  11. }
  12. bzero(&servaddr,sizeof(servaddr));
  13. servaddr.sin_family=AF_INET;
  14. servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
  15. servaddr.sin_port=htons(5566);
  16. int ret;
  17. ret=connect_timeout(sockfd,&servaddr,5);
  18. if(ret == -1 && errno == ETIMEDOUT){
  19. puts("timeout ...");
  20. return 1;
  21. }else if(ret == -1)
  22. err_quit("connect");
  23. bzero(buf,sizeof(buf));
  24. printf("%d\n",++i);
  25. }
  26. }

关于FD_SETSIZE的最大集合:

上面的客户端同时开三个连接上一版的服务器,过一会儿就能看到效果,程序会在accept返回-1

poll的使用

  1. #include <unistd.h>
  2. #include <poll.h>
  3. #include <netdb.h>
  4. #include <errno.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <signal.h>
  9. #include <sys/wait.h>
  10. #include <sys/select.h>
  11. #include <sys/socket.h>
  12. #include <arpa/inet.h>
  13. #include <netinet/in.h>
  14. #define MAX(a,b) a>b?a:b;
  15. void err_quit(const char *s){
  16. perror(s);
  17. exit(1);
  18. }
  19. ssize_t readn(int fd,void *buff,size_t count){
  20. char *buffp;
  21. ssize_t nread;
  22. size_t nleft;
  23. buffp=(char *)buff;
  24. nleft=count;
  25. while(nleft > 0){
  26. if((nread = read(fd,buffp,nleft)) < 0){
  27. if(errno == EINTR)
  28. continue;
  29. else
  30. return -1;
  31. }else if(nread == 0)
  32. break;
  33. nleft -= nread;
  34. buffp += nread;
  35. }
  36. return count-nleft;
  37. }
  38. ssize_t writen(int fd,const void *buff,size_t n){
  39. size_t nleft;
  40. ssize_t nwritten;
  41. const char *ptr;
  42. ptr=buff;
  43. nleft=n;
  44. while(nleft > 0){
  45. if((nwritten=write(fd,ptr,nleft)) < 0){
  46. if(nwritten < 0 && errno == EINTR)
  47. continue;
  48. else
  49. return -1;
  50. }else if(nwritten == 0)
  51. break;
  52. nleft -= nwritten;
  53. ptr += nwritten;
  54. }
  55. return n-nleft;
  56. }
  57. ssize_t recv_peek(int fd,void *buf,size_t len){
  58. ssize_t ret;
  59. while(1){
  60. ret=recv(fd,buf,len,MSG_PEEK);
  61. if(ret == -1 && errno == EINTR)
  62. continue;
  63. return ret;
  64. }
  65. }
  66. ssize_t readline(int fd,void *buf,size_t maxline){
  67. ssize_t ret;
  68. size_t nread;
  69. size_t nleft;
  70. char *bufp;
  71. bufp=buf;
  72. nleft=maxline;
  73. while(1){
  74. ret=recv_peek(fd,buf,nleft);
  75. if(ret < 0)
  76. return ret;
  77. else if(ret == 0)
  78. return ret;
  79. nread=ret;
  80. int i;
  81. for(i=0;i<nread;i++){
  82. if(bufp[i] == '\n'){
  83. ret=readn(fd,bufp,i+1);
  84. if(ret != i+1)
  85. err_quit("readn");
  86. return ret;
  87. }
  88. }
  89. if(nread > nleft)
  90. err_quit("readn");
  91. nleft -= nread;
  92. ret=readn(fd,bufp,nread);
  93. if(ret != nread)
  94. err_quit("readn");
  95. bufp += nread;
  96. }
  97. return -1;
  98. }
  99. int accept_timeout(int fd,struct sockaddr_in *addr,unsigned int wait_seconds){
  100. int ret;
  101. socklen_t addrlen=sizeof(struct sockaddr_in);
  102. if(wait_seconds > 0){
  103. fd_set accept_fdset;
  104. struct timeval timeout;
  105. FD_ZERO(&accept_fdset);
  106. FD_SET(fd,&accept_fdset);
  107. timeout.tv_usec=0;
  108. timeout.tv_sec=wait_seconds;
  109. do{
  110. ret=select(fd+1,&accept_fdset,NULL,NULL,&timeout);
  111. }while(ret < 0 && errno == EINTR);
  112. if(ret == 0){
  113. errno = ETIMEDOUT;
  114. return -1;
  115. }else if(ret == -1)
  116. return -1;
  117. }
  118. if(addr != NULL)
  119. ret=accept(fd,(struct sockaddr *)addr,&addrlen);
  120. else
  121. ret=accept(fd,NULL,NULL);
  122. if(ret == -1)
  123. err_quit("accept");
  124. return ret;
  125. }
  126. int main(int argc,char *argv[]){
  127. int i,maxi,tmpfd,sockfd,connfd;
  128. socklen_t len;
  129. struct sockaddr_in addr,client;
  130. int nready;
  131. struct pollfd clientfd[2048];
  132. ssize_t n;
  133. char buf[1024];
  134. if((sockfd=socket(PF_INET,SOCK_STREAM,0)) < 0)
  135. err_quit("sockfd");
  136. bzero(&addr,sizeof(addr));
  137. addr.sin_family=AF_INET;
  138. addr.sin_addr.s_addr=htonl(INADDR_ANY);
  139. addr.sin_port=htons(5566);
  140. int on=1;
  141. if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) <0)
  142. err_quit("setsockopt");
  143. if(bind(sockfd,(struct sockaddr *)&addr,sizeof(addr))<0)
  144. err_quit("bind");
  145. if(listen(sockfd,10)<0)
  146. err_quit("listen");
  147. maxi=0;
  148. for(i=0;i<2048;i++)
  149. clientfd[i].fd=-1;
  150. clientfd[0].fd=sockfd;
  151. clientfd[0].events= POLLIN;
  152. while(1){
  153. nready=poll(clientfd,maxi+1,-1);
  154. if(nready == -1){
  155. if(errno == EINTR)
  156. continue;
  157. else
  158. err_quit("select");
  159. }
  160. if(clientfd[0].revents & POLLIN){
  161. len=sizeof(client);
  162. connfd=accept(sockfd,(struct sockaddr *)&client,&len);
  163. if(connfd < 0)
  164. err_quit("accept");
  165. for(i=0;i<2048;i++){
  166. if(clientfd[i].fd < 0){
  167. clientfd[i].fd=connfd;
  168. clientfd[i].events=POLLIN;
  169. if(i > maxi)
  170. maxi=i;
  171. break;
  172. }
  173. }
  174. if(i == 2048)
  175. err_quit("too many clients");
  176. if(--nready <= 0)
  177. continue;
  178. }
  179. for(i=1;i<=maxi;i++){
  180. if((tmpfd=clientfd[i].fd) < 0)
  181. continue;
  182. if(clientfd[i].revents & POLLIN){
  183. bzero(buf,sizeof(buf));
  184. if((n=readline(tmpfd,buf,sizeof(buf))) == 0){
  185. close(tmpfd);
  186. clientfd[i].fd=-1;
  187. }
  188. write(STDOUT_FILENO,buf,n);
  189. writen(tmpfd,buf,n);
  190. if(--nready <= 0)
  191. break;
  192. }
  193. }
  194. }
  195. }

select的限制与poll的使用的更多相关文章

  1. select、pselect、poll和epoll的区别

    select.pselect.poll和epoll函数是unix中具有I/O复用的函数.什么是I/O复用?为什么要有I/O复用?以及在什么场合下使用I/O复用?既然都具有I/O复用的功能,那这几个函数 ...

  2. select的限制以及poll的使用

    1.先说select在多路IO中的限制:1)linux中每个程序能够打开的最多文件描述符是有限制的.默认是1024.可以通过ulimit -n进行查看和修改: xcy@xcy-virtual-mach ...

  3. UNIX环境高级编程——I/O多路转接(select、pselect和poll)

    I/O多路转接:先构造一张有关描述符的列表,然后调用一个函数,直到这些描述符中的一个已准备好进行I/O时,该函数才返回.在返回时,它告诉进程哪些描述符已准备好可以进行I/O. poll.pselect ...

  4. Socket编程实践(10) --select的限制与poll的使用

    select的限制 用select实现的并发服务器,能达到的并发数一般受两方面限制: 1)一个进程能打开的最大文件描述符限制.这可以通过调整内核参数.可以通过ulimit -n(number)来调整或 ...

  5. socket编程以及select、epoll、poll示例详解

    socket编程socket这个词可以表示很多概念,在TCP/IP协议中“IP地址 + TCP或UDP端口号”唯一标识网络通讯中的一个进程,“IP + 端口号”就称为socket.在TCP协议中,建立 ...

  6. (转载) Linux IO模式及 select、poll、epoll详解

    注:本文是对众多博客的学习和总结,可能存在理解错误.请带着怀疑的眼光,同时如果有错误希望能指出. 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案 ...

  7. Linux下select&poll&epoll的实现原理(一)

    最近简单看了一把 linux-3.10.25 kernel中select/poll/epoll这个几个IO事件检测API的实现.此处做一些记录.其基本的原理是相同的,流程如下 先依次调用fd对应的st ...

  8. Python自动化 【第十篇】:Python进阶-多进程/协程/事件驱动与Select\Poll\Epoll异步IO

    本节内容: 多进程 协程 事件驱动与Select\Poll\Epoll异步IO   1.  多进程 启动多个进程 进程中启进程 父进程与子进程 进程间通信 不同进程间内存是不共享的,要想实现两个进程间 ...

  9. 聊聊IO多路复用之select、poll、epoll详解

    本文转载自: http://mp.weixin.qq.com/s?__biz=MzAxODI5ODMwOA==&mid=2666538922&idx=1&sn=e6b436ef ...

随机推荐

  1. vue-router 路由元信息 终于搞明白了路由元信息是个啥了

    vue-router 路由元信息:https://blog.csdn.net/wenyun_kang/article/details/70987840 终于搞明白了路由元信息是个啥了:https:// ...

  2. LOJ 2234/BZOJ 3629 聪明的燕姿(数论+DFS)

    题面 传送门 分析 看到约数之和,我们首先想到约数和公式 若$ x=\prod_{i=1}^{n}p_i^{k_i} \(,则x的约数和为\) \prod_{i=1}^{n} \sum_{j=0}^{ ...

  3. Java并发编程:Concurrent锁机制解析

    Java并发编程:Concurrent锁机制解析 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: # ...

  4. Zookeeper之启动常见错误及解决方法

    Zookeeper启动后,有时候没有真正的启动,那我们如何查找错误呢,就可以查看zookeeper目录下面的zookeeper.out文件,就可以查看到错误了.zookeeper.out文件比较的重要 ...

  5. 我心中的ASP.NET Core 新核心对象WebHost(二)

    这是ASP.NET Core新核心对象系列的第二篇,上一篇 WebHost准备阶段 我们讲到了WebHostBuilder的初始化及配置.我们给WebHostBuilder进行以下配置 UseKest ...

  6. 【JAVA】 05-String类和JDK5

    链接: 笔记目录:毕向东Java基础视频教程-笔记 GitHub库:JavaBXD33 目录: <> <> 内容待整理: API-String 特点 String类: 1.St ...

  7. 【JAVA】java编译错误:编码UTF8/GBK的不可映射字符

    环境: win7 cmd窗口编译 javac xx.java时报错 错误显示:错误:编码GBK的不可映射字符 背景: 分析发现是中文字符所在行报错了 查阅相关资料发现,是因为编译器设置为了utf-8, ...

  8. rabbitmq windows安装 及 centos安装

     windows安装如下: 安装方法如下网址: https://baijiahao.baidu.com/s?id=1605656085633071281&wfr=spider&for= ...

  9. OtterCTF - Reverse - Msg Me This

    原文地址:Msg Me This 题目 Category: Reverse Engineering Points: 500 Solves: 15 Description: Rick created a ...

  10. Strcpy,strcpy使用注意

    一.char *strcpy(char *dest, const char *src) 参数 dest -- 指向用于存储复制内容的目标数组. src -- 要复制的字符串. 注意: 1.dest需要 ...