Select 网络模型

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;
           }
       }



   }
}



}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值