select 与 I/O多路转接
参考博客:http://blog.sina.com.cn/s/blog_607072980102uxcw.html
I/0多路转接:
描述符表示某个I/O。构造一张有关描述符的数据表,调用select函数,返回准备就绪的描述符,如果没有描述符准备好,则一直阻塞,超时返回0。
int select( int maxfdp1, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, sturct timeval *tvptr);
返回:准备就绪的描述符,若超时则为0,若出错则为-1
maxfdp1为最大描述符值,设置为一个常数;
readfds、writefds、exceptfds是指向描述符集的指针,表示我们关心的可读、可写和处异常条件的描述符;
tvptr表示愿意等待的时间(秒、微秒),tvptr=NULL在捕捉到信号前永远等待。
描述符集
fd_set rset; //描述符集
int fd; //描述符集的位,表示一个描述符
FD_ZERO(fd_set *fdset); //清空fdset中的所有位
FD_SET(int fd, fd_set *fdset); //在fdset中打开fd所对应的位
FD_CLR(int fd, fd_set *fdset); //在fdset中关闭fd所对应的位
FD_ISSET(int fd, fd_set *fdset); //测试fd是否在fdset中
socket单线程并发程序select代码:
int main(int argc,char* argv[]) { int ret,n; int sockFd; struct sockaddr_in servAddr; fd_set oset,nset; char strBuf[BUFSIZE]; //UDP地址绑定到服务器 if(argc!=3) errexit("USAGE:%s hostname port",argv[0]); sockFd=connectSock(argv[1],argv[2],"udp"); //初始化fd_set对象 FD_ZERO(&oset); FD_SET(STDIN_FILENO,&oset); FD_SET(sockFd,&oset); nset=oset; while(1) { ret=select(4,&nset,NULL,NULL,0); if(FD_ISSET(sockFd,&nset)) { memset(strBuf,0,BUFSIZE); recv(sockFd,strBuf,BUFSIZE,0); printf("%s",strBuf); } if(FD_ISSET(STDIN_FILENO,&nset)) { fgets(strBuf,BUFSIZE,stdin); send(sockFd,strBuf,sizeof(strBuf),0); memset(strBuf,0,BUFSIZE); } nset=oset; } }