select的限制

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

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

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

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

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

关于FD_SETSIZE的最大集合:

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

poll的使用

#include <unistd.h>
#include <poll.h>
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h> #define MAX(a,b) a>b?a:b; void err_quit(const char *s){
perror(s);
exit(1);
} ssize_t readn(int fd,void *buff,size_t count){
char *buffp;
ssize_t nread;
size_t nleft; buffp=(char *)buff;
nleft=count;
while(nleft > 0){
if((nread = read(fd,buffp,nleft)) < 0){
if(errno == EINTR)
continue;
else
return -1;
}else if(nread == 0)
break;
nleft -= nread;
buffp += nread;
}
return count-nleft;
} ssize_t writen(int fd,const void *buff,size_t n){
size_t nleft;
ssize_t nwritten;
const char *ptr; ptr=buff;
nleft=n;
while(nleft > 0){
if((nwritten=write(fd,ptr,nleft)) < 0){
if(nwritten < 0 && errno == EINTR)
continue;
else
return -1;
}else if(nwritten == 0)
break;
nleft -= nwritten;
ptr += nwritten;
}
return n-nleft;
} ssize_t recv_peek(int fd,void *buf,size_t len){
ssize_t ret;
while(1){
ret=recv(fd,buf,len,MSG_PEEK);
if(ret == -1 && errno == EINTR)
continue;
return ret;
}
} ssize_t readline(int fd,void *buf,size_t maxline){
ssize_t ret;
size_t nread;
size_t nleft;
char *bufp; bufp=buf;
nleft=maxline;
while(1){
ret=recv_peek(fd,buf,nleft);
if(ret < 0)
return ret;
else if(ret == 0)
return ret; nread=ret;
int i;
for(i=0;i<nread;i++){
if(bufp[i] == '\n'){
ret=readn(fd,bufp,i+1);
if(ret != i+1)
err_quit("readn"); return ret;
}
} if(nread > nleft)
err_quit("readn"); nleft -= nread;
ret=readn(fd,bufp,nread);
if(ret != nread)
err_quit("readn"); bufp += nread;
} return -1;
} int accept_timeout(int fd,struct sockaddr_in *addr,unsigned int wait_seconds){
int ret;
socklen_t addrlen=sizeof(struct sockaddr_in); if(wait_seconds > 0){
fd_set accept_fdset;
struct timeval timeout; FD_ZERO(&accept_fdset);
FD_SET(fd,&accept_fdset); timeout.tv_usec=0;
timeout.tv_sec=wait_seconds;
do{
ret=select(fd+1,&accept_fdset,NULL,NULL,&timeout);
}while(ret < 0 && errno == EINTR); if(ret == 0){
errno = ETIMEDOUT;
return -1;
}else if(ret == -1)
return -1;
} if(addr != NULL)
ret=accept(fd,(struct sockaddr *)addr,&addrlen);
else
ret=accept(fd,NULL,NULL);
if(ret == -1)
err_quit("accept"); return ret;
} int main(int argc,char *argv[]){
int i,maxi,tmpfd,sockfd,connfd;
socklen_t len;
struct sockaddr_in addr,client;
int nready;
struct pollfd clientfd[2048];
ssize_t n;
char buf[1024]; if((sockfd=socket(PF_INET,SOCK_STREAM,0)) < 0)
err_quit("sockfd"); bzero(&addr,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY);
addr.sin_port=htons(5566); int on=1;
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) <0)
err_quit("setsockopt"); if(bind(sockfd,(struct sockaddr *)&addr,sizeof(addr))<0)
err_quit("bind"); if(listen(sockfd,10)<0)
err_quit("listen"); maxi=0;
for(i=0;i<2048;i++)
clientfd[i].fd=-1; clientfd[0].fd=sockfd;
clientfd[0].events= POLLIN;
while(1){
nready=poll(clientfd,maxi+1,-1); if(nready == -1){
if(errno == EINTR)
continue;
else
err_quit("select");
} if(clientfd[0].revents & POLLIN){
len=sizeof(client);
connfd=accept(sockfd,(struct sockaddr *)&client,&len);
if(connfd < 0)
err_quit("accept"); for(i=0;i<2048;i++){
if(clientfd[i].fd < 0){
clientfd[i].fd=connfd;
clientfd[i].events=POLLIN;
if(i > maxi)
maxi=i;
break;
}
}
if(i == 2048)
err_quit("too many clients"); if(--nready <= 0)
continue;
} for(i=1;i<=maxi;i++){
if((tmpfd=clientfd[i].fd) < 0)
continue;
if(clientfd[i].revents & POLLIN){
bzero(buf,sizeof(buf));
if((n=readline(tmpfd,buf,sizeof(buf))) == 0){
close(tmpfd);
clientfd[i].fd=-1;
}
write(STDOUT_FILENO,buf,n);
writen(tmpfd,buf,n); if(--nready <= 0)
break;
}
}
}
}

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. Python入门习题4.文本进度条

    例4.1.设置一组文本进度条,使之运行效果如下: --------执行开始--------% 0 [->**********]%10 [*->*********]%20 [**->* ...

  2. php提交表单时如何保留多个空格及换行的文本样式

    需求是:用户提交表单时屏蔽敏感词的功能.其中敏感词来自服务器端同一路径下的ciku.txt,敏感词通过"|"连接,例如"g|c|a",提交表单时替换敏感词,更重 ...

  3. mt-picker 样式修改

    // html : <div class="applyInformations" @click="chooseSex"> <p>性别&l ...

  4. shell脚本从入门到精通(初级)之入门篇

    写在开头 本文是阅读<Linux命令行与shell脚本编程大全>时的一些笔记,主要是shell脚本的一些基本语法, 还有很多细节和高级内容没有写到. 笔者也是shell script菜鸟, ...

  5. JS的组成和变量

    JavaScript中的变量和数据类型 Js做客户端语言 按照相关的Js语法,去操作页面中的元素,有时还要操作浏览器里面的一些功能 Js由三部分组成: ECMAScript(ES):描述了该语言的语法 ...

  6. Zen Coding – 超快地写网页代码(注:已更名为Emmet)

    这篇博客能帮助快速上手这款插件,极大地提高开发效率废话不多说直接上例子 zen codeing的缩写规则 E 元素名 (div, p); 实例:(输入完<按快捷键ctrl+E>就会显示) ...

  7. Vue:替换/合并现有的特性

    假设这是 bs-date-input 的模板: <input type="date" class="form-control"> 为了给该日期选择器 ...

  8. ElasticSearch java api -单例模式

    //单例模式 private static Settings getSettingInstance(){ if(settings==null){ synchronized (Settings.clas ...

  9. Swagger添加文件上传测试

    先上对比图 图一无法选择文件,图二可以选择文件 图一 图二 添加过滤器 public class SwaggerFileUploadFilter : IOperationFilter { /// &l ...

  10. centos6.5 相关命令

    挂载U盘 1.进入mnt目录: #cd /mnt 2.新建一个USB目录: #mkdir usb 3.查看U盘的目录: #fdisk –l 4.挂载: #mount –t vfat /dev/sdb1 ...