select函数详解及使用案例

1、select函数原型

int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);

参数解释:

 maxfdp——传入参数,集合中所有文件描述符的范围,即最大文件描述符值+1
 readfds——传入传出参数,select调用时传入要监听的可读文件描述符集合,select返回时传出发生可读事件的文件描述符集合
 writefds——传入传出参数,select调用时传入要监听的可写文件描述符集合,select返回时传出发生可写事件的文件描述符集合
 errorfds——传出参数,select返回时传出发生事件(包括可读和可写)中异常事件的文件描述符集合
 timeout——传入参数,设置select阻塞的时间。若设置为NULL,则select一直阻塞直到有事件发生;
                                      若设置为0,则select为非阻塞模式,执行后立即返回;
                                      若设置为一个大于0的数,即select的阻塞时间,若阻塞时间内有事件发生就返回,否则时间到了立即返回

fd_set是自定义的一个数据结构,可看作一个集合,存放可读、可写或异常事件的文件描述符。fd_set集合通常有以下四个宏来操作:

void FD_ZERO(fd_set *fdset);  //清空fdset中所有文件描述符
void FD_SET(int fd,fd_set *fdset);  //添加文件描述符fd到集合fdset中
void FD_CLR(int fd,fd_set *fdset); //将文件描述符fd从集合fdset中去除
int FD_ISSET(int fd,fd_set *fdset);  //判断文件描述符fd是否在集合fdset中

select工作原理:传入要监听的文件描述符集合(可读、可写或异常)开始监听,select处于阻塞状态,当有事件发生或设置的等待时间timeout到了就会返回,返回之前自动去除集合中无事件发生的文件描述符,返回时传出有事件发生的文件描述符集合。但select传出的集合并没有告诉用户集合中包括哪几个就绪的文件描述符,需要用户后续进行遍历操作。

2、select优缺点

优点:

(1)select的可移植性较好,可以跨平台;
(2)select可设置的监听时间timeout精度更好,可精确到微秒,而poll为毫秒。

缺点:

(1)select支持的文件描述符数量上限为1024,不能根据用户需求进行更改;
(2)select每次调用时都要将文件描述符集合从用户态拷贝到内核态,开销较大;
(3)select返回的就绪文件描述符集合,需要用户循环遍历所监听的所有文件描述符是否在该集合中,当监听描述符数量很大时效率较低。

3、select使用经典案例

用select函数编写一个简单的高并发服务器,且假设服务器启动时处于无连接状态,满足以下功能:
a)可处理来自一个新客户端的连接请求;
b)监听可读事件,若已连接客户端的已连接描述符发生可读事件,服务器从客户端读取数据并处理;

服务器端代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<ctype.h>

#define SERV_PORT 6666

int main()
{
   
  int i,j,n,maxi;
  int maxfd,listenfd,connfd,sockfd;
  int nready,client[FD_SETSIZE-1];  //FD_SETSIZE=1024,定义数组client来储存已连接描述符,最多1023个
  char buf[BUFSIZ], str;

  struct sockaddr_in clie_addr,serv_addr;
  socklen_t clie_addr_len;
  fd_set allset,readset;  //定义监听描述符集合allset和发生事件描述符集合readset
 
  bzero(&serv_addr,sizeof(serv_addr));
  serv_addr.sin_family=AF_INET;
  serv_addr
  • 20
    点赞
  • 180
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值