select和poll函数、shutdown函数

 select函数

头文件 <sys/select.h>  <sys/time.h>

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

该函数允许进程指示内核等待多个事件中的任何一个发送,并且只有在一个或多个事件发生或经历一段时间后才唤醒它

timeval的定义如下:

struct timeval 
{
 long tv_sec; //秒
 long tv_usec; //毫秒
}
  1. 当timeout参数取NULL时,则select()阻塞等待;
  2. 当timeout参数结构体中两个项都为0时,则select()立即返回,相当于轮询;
  3. 当timeout参数结构体中不全为0时,等待指定时间后返回。

select()函数会修改timeout中的值,以表示函数返回距离设定的时间之间的差,即剩余时间。因此,每次循环需要对timeout重新设值。

中间三个参数readfds、writefds和errorfds指定要让内核测试读、写和异常条件的描述符,如果不指定,则设为NULL。

如果把readfds、writefds和errorfds三个参数都设置为NULL,那么select这个时候就可以当计时器适用

maxfdp指待测试的描述符的个数,即最大描述符+1

处理fset类型的数据,需要用到以下几个宏:

FD_ZERO(fd_set *fdset)  清空fdset中的所有元素,即fd每位都赋值0 

FD_SET(int fd, fd_set *fdset)  把fd元素添加到fdset, 即第fd位赋值1

FD_CLR(int fd, fd_set *fdset):把fd元素从fdset删除, 即第fd位赋值0 

FD_ISSET(int fd, fdset *fdset):检测fd是否在集合fdset中,即检测fdset的第fd位是否为1  

每次select返回时,都会修改readfds、writefds和errorfds的值,从而指示哪些描述符已就绪,每个描述符需要进行的操作

由于这三个参数都是值-结果类型,因此每次使用select函数之前,都要把readfds、writefds和errorfds的值重新设置

select的返回值表示已经准备就绪的描述符数量,当出错时返回-1

描述符就绪条件

当描述符就绪时,就会加入到就绪队列。这时该描述符才可能从accept或者select、poll等函数返回

带外异常:IO异常

低水位标记:当接受或发送缓存区的数据字节数小于这个值时,阻塞,大于等于这个值时,返回

​​​​​​​1. 满足以下其中一个条件,套接字准备好读

​​​​​​​    (1) 套接字接收缓冲区的数据字节数 大于等于 套接字接收缓冲区的低水位标记大小 ,低水位标记默认为1

​​​​​​​    (2) 该连接的读半部关闭,即接收了FIN

​​​​​​​    (3) 该套接字是一个监听套接字,且有新的连接加入

​​​​​​​    (4) 有套接字的错误待处理,这样的套接字的读操作不阻塞,并返回-1

2. 满足以下其中一个条件,套接字准备好写的条件

   (1)套接字发送缓冲区的数据字节数 大于等于 套接字发送缓冲区的低水位标记大小 ,并且该套接字已连接,或者该套接字不需要连接(如UDP) 

​​​​​​​   (2) 该连接的写半部关闭,对这样的套接字的写操作将产生SIGPIPE信号

​​​​​​​   (3) 使用connect的套接字已经建立连接

​​​​​​​   (4) 有套接字错误待处理,将不阻塞,并返回-1,同时把errno设为确定的错误条件

注意:当某个套接字上发生错误时,它会将select的  值结果类型数据 中被标记为即可写,又可读

poll函数

头文件 <poll.h>

int poll(struct pollfd *fdarray, unsigned long nfds, int timeout)

第一个参数指向一个pollfd结构体类型数组fdarray,pollfd结构体结构如下:

struct pollfd
{
    int fd;
    short events;
    short revent;
}

通过fdarray结构体数组,可以登记要监听的描述符

其中,fd是具体要监听的描述符,event指定监听的事件类型,比如 读、写 或者异常  revent返回监听的结果

具体的说,对于event

要监听读事件,则  event = POLLRDNORM

要监听写事件,则 event = POLLWRNORM

读写都监听,则event = POLLRDNORM | POLLWRNORM

监听错误,则 event = POLLERR

对于revent

要确定套接字是否可读,则 判定条件为: revent &POLLRDNORM

要确定套接字是否可读,则 判定条件为: revent &POLLWRNORM

要确定套接字既可读又可写,则判定条件为: revent & (POLLRDNORM | POLLWRNORM)

要确定套接字是否发生错误,则判定条件为:revent & POLLERR

nfds指定fdarray结构体数组的元素数目

timeout指定poll返回前阻塞的最长时间

正常情况下,poll函数返回就绪描述符的个数,即revent元素值非0的描述符个数,发生错误时,返回-1

shutdown函数

头文件<sys/socket.h>

使用close关闭描述符,有两个限制:

  1. close把描述符引用减1,仅在该计数变为0时才关闭套接字
  2. close同时终止读和写两个方向的传送

shutdown可以避免这两个局限

int shutdown(int sockfd, int howto)

该函数的行为依赖于howto的值

SHUT_RD  关闭连接的读这一半,丢弃套接字接收缓冲区的数据,接收到的新的数据都被确认,然后丢弃

SHUT_WR 关闭连接的写这一半, 丢弃套接字发送缓冲区的数据,后跟正常的TCP终止序列,无论套接字的引用描述符是否为0

SHUT_RDWR  同时关闭连接的读半部和写半步,这与调用两次shutdown等效

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值