maxfd 最大描述符加1
fd_set操作集合
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int maxfdp, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeval *timeout);
maxfdp:被监听的文件描述符的总数,它比所有文件描述符集合中的文件描述符的最大值大1,因为文件描述符是从0开始计数的;
readfds、writefds、exceptset:分别指向可读、可写和异常等事件对应的描述符集合。
timeout:用于设置select函数的超时时间,即告诉内核select等待多长时间之后就放弃等待。timeout == NULL 表示等待无限长的时间
timeval结构体定义如下:
struct timeval
{
long tv_sec; /*秒 */
long tv_usec; /*微秒 */
};
返回值:超时返回0;失败返回-1;成功返回大于0的整数,这个整数表示就绪描述符的数目。
以下介绍与select函数相关的常见的几个宏:
#include <sys/select.h>
int FD_ZERO(int fd, fd_set *fdset); //一个 fd_set类型变量的所有位都设为 0
int FD_CLR(int fd, fd_set *fdset); //清除某个位时可以使用
int FD_SET(int fd, fd_set *fd_set); //设置变量的某个位置位
int FD_ISSET(int fd, fd_set *fdset); //测试某个位是否被置位
select使用范例:
当声明了一个文件描述符集后,必须用FD_ZERO将所有位置零。之后将我们所感兴趣的描述符所对应的位置位,操作如下:
fd_set rset;
int fd;
FD_ZERO(&rset);
FD_SET(fd, &rset);
FD_SET(stdin, &rset);
然后调用select函数,拥塞等待文件描述符事件的到来;如果超过设定的时间,则不再等待,继续往下执行。
select(fd+1, &rset, NULL, NULL,NULL);
select返回后,用FD_ISSET测试给定位是否置位:
if(FD_ISSET(fd, &rset)
{
…
//do something
}
select(maxfd+1, )
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <strings.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <sys/select.h>
#define MAX_BUFFER_SIZE 128
int mz_ipv4_tcp_create_socket()
{
int listenfd, sockfd, opt = 1;
struct sockaddr_in server, client;
socklen_t len;
int timep;
int ret;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if(listenfd < 0){
perror("Create socket fail.");
return -1;
}
if((ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < 0){
perror("Error, set socket reuse addr failed");
return -1;
}
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(8888);
server.sin_addr.s_addr = htonl(INADDR_ANY);
len = sizeof(struct sockaddr);
if(bind(listenfd, (struct sockaddr *)&server, len)<0){
perror("bind error.");
return -1;
}
listen(listenfd, 10);
return listenfd;
}
int main(int argc,char *argv[])
{
int listenfd,sockfd,maxfd,fd[1024];
struct sockaddr_in clienaddr;
socklen_t len;
fd_set readfd,tmpfd;
int ret;
int i=0;
char readbuf[100];
memset(readbuf,0,sizeof(readbuf));
listenfd=mz_ipv4_tcp_create_socket();
FD_ZERO(&readfd);
FD_SET(listenfd,&readfd);
maxfd=listenfd;
printf("maxfd:%d\n",maxfd);
len =1;
while(1)
{
tmpfd=readfd;
ret =select(maxfd+1,&tmpfd,NULL,NULL,NULL); //last null is zuse
if(ret ==-1)
{
perror("select error");
exit(1);
}//you wen jian miao shu fu ke du le
if(FD_ISSET(listenfd,&tmpfd))// shi fou you ke hu duan fa qi lian jie
{
for(i=0;i<1024;i++)
{
if(fd[i]==0)
{
break;
}
}
fd[i] = accept(listenfd, (struct sockaddr *)&clienaddr, &len);
if(fd[i]==-1)
{
perror("accept error");
exit(1);
}
printf("ip from:%s fd=%d\n",inet_ntoa(clienaddr.sin_addr),fd[i]);
FD_SET(fd[i],&readfd);
if(maxfd <fd[i])
{
maxfd=fd[i];
printf(" accept maxfd:%d\n",maxfd);
}
}else {// you ke fu duan fa xiao xi
for(i=0;i<1024;i++)
{
if(FD_ISSET( fd[i],&tmpfd))//pan duan nage id ke du
{
ret=recv(fd[i],readbuf,sizeof(readbuf),0);
if(ret ==-1)
{
perror("recv error");
}else if(ret ==0)
{
close(fd[i]);
fd[i]=0;
FD_CLR(fd[i],&readfd);
printf("close fd\n");
}else{
printf(" recv from -%d -data:%s\n",fd[i],readbuf);
}
memset(readbuf,0,sizeof(readbuf));
break;
}
}
}
}
}