UNIX网络编程之IO复用(一):select系统调用
来源:互联网 发布:免费瓷砖设计软件 编辑:程序博客网 时间:2024/06/05 05:01
select系统调用的原型
select系统调用的功能是:在一段指定的时间内,监听用户感兴趣的文件描述符上的可读、可写和异常事件。它的原型如下:
#include <sys/select.h>#include <sys/time.h>int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout);
两种数据结构fd_set和timeval
我们先来了解select系统调用涉及到的数据类型。
首先介绍fd_set。它表示文件描述符的集合,用宏实现,定义如下:
#include <typesizes.h>#define __FD_SETSIZE 1024#include <sys/select.h>#define FD_SETSIZE __FD_SETSIZEtypedef long int __fd_mask;#undef __NFDBITS#define __NFDBITS (8 * (int)sizeof(__fd_mask))typedef struct{#ifdef __USE_XOPEN __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];#define __FDS_BITS(set) ((set)->fds_bits)#else __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];#define __FDS_BITS(set) ((set)->__fds_bits)#endif}fd_set;
由上述定义可知,fd_set结构体仅包含一个整型数组,数组中的每一位标记一个文件描述符。fd_set能容纳的文件描述符的数量由FD_SETSIZE指定,这就限制了select能同时监听的文件描述符的数量。
UNIX提供了如下一组宏来访问fd_set结构体中的位:
#include <sys/select.h>FD_ZERO(fd_set *fdset); // 清除fdset的所有位FD_SET(int fd, fd_set *fdset); // 设置fdset的位fdFD_CLR(int fd, fd_set *fdset); // 清除fdset的位fdint FD_ISSET(int fd, fd_set *fdset); // 测试fdset的位fd是否被设置
然后介绍struct timeval结构体,它的定义如下:
struct timeval{ long tv_sec; // 秒数 long tv_usec; // 微秒数}
各参数和返回值的含义
然后了解各个参数代表的含义:
- maxfdp1是一个值参数,表示感兴趣的文件描述符的最大值加1。
- readset、writeset和exceptset都是值-结果参数。进入select时,作为值参数,分别表示感兴趣的文件描述符上的可读、可写和异常事件的集合;从select返回时,作为结果参数,分别表示感兴趣的文件描述符上的可读就绪、可写就绪和异常就绪的事件的集合。
- timeout也是一个值-结果参数。进入select时,作为值参数,表示select可以阻塞的最大时间;从select返回时,作为结果参数,表示剩余的时间,通过剩余的时间,可以计算进程阻塞在select上的时间。如果给timeout的tv_sec成员和tv_usec成员都传递0,则select立即返回。如果给timeout传递NULL,则select一直阻塞,直到某个文件描述符就绪。
返回值的含义:
select成功时返回就绪(可读,可写和异常)的文件描述符的总数。如果在超时时间内没有任何文件描述符就绪,则select返回0。select失败时返回-1并设置errno。如果在select阻塞期间,程序收到信号,则select被信号中断,立即返回-1,并设置errno=EINTR。
文件描述符的就绪条件
了解了select系统调用原型的各部分含义后,我们需要知道哪些条件下文件描述符可读就绪,哪些条件下文件描述符可写就绪,以及哪些条件下文件描述符出现异常。现总结如下:
- 可读就绪的条件
- socket内核接收缓冲区中的字节数大于或等于其低水位标记SO_RCVLOWAT。此时我们可以无阻塞的读该socket,并且读操作返回的字节数大于0。
- socket通信的对方关闭连接,即接收到对方的FIN报文。此时对该socket的读操作将返回0。其实,反过来我们可以通过读操作返回0判断对方是否关闭了连接。
- 监听socket上有未处理的连接请求,即socket通信双方完成了三次握手。此时,我们可以通过accept系统调用获取连接。
- socket上有未处理的错误。此时,我们可以使用getsockopt来读取和清除该错误。
- 可写就绪的条件
- socket内核发送缓冲区的可用字节数大于或等于其低水位标记SO_SNDLOWAT。此时,我们可以无阻塞的写该socket,并且写操作返回的字节数大于0。
- socket的写操作被关闭。对写操作关闭的socket执行写操作将触发一个SIGPIPE信号。通常,如果socket通信的对方使用close关闭连接时,如果本方发送缓冲区不为空,那么可以执行第一次写操作,对方的TCP会回复一个RST报文,此时本方socket关闭连接,当本方执行第二次写操作时将触发一个SIGPIPE信号。
- socket使用非阻塞connect连接成功或失败(超时)之后。此时,无论连接成功或失败,都可以对socket进行写操作。不过连接失败时,写数据必然失败。所以我们可以在select返回后再使用非阻塞connect连接一次,若errno=EISCONN,那么说明连接成功,可以进行数据的读写。
- socket上有未处理的错误。此时我们可以用getsockopt来读取和清除该错误。
- 异常的条件
- select能处理的异常情况只有一种:socket上接收到带外数据。
未完待续。。。
阅读全文
1 0
- UNIX网络编程之IO复用(一):select系统调用
- Linux/Unix IO多路复用之select网络编程(含源码)
- Linux/Unix IO多路复用之select网络编程(含源码)
- Linux/Unix IO多路复用之select网络编程基本代码
- Unix网络编程之IO复用
- unix 网络编程--select (一)
- unix--网络编程IO复用
- Unix网络编程之广播(一)
- 【网络编程】IO 多路复用之 select 总结
- 高性能网络编程 - select系统调用
- linux网络编程之用select方法实现io复用(基于udp)
- linux网络编程之用select函数实现io复用(基于TCP)引发的思考
- unix网络编程笔记(四)--IO复用
- unix网络编程(五)--IO复用+非阻塞
- UNIX网络编程(一)
- select和poll函数《UNIX网络编程卷一》笔记
- unix 网络编程 select 讲解
- UNIX网络编程卷一:第六章 I/O 复用 select, poll
- Struts2中Action类的方法调用
- P3925,一道线段树合并题
- ip,TCP,UDP,HTTP,TCP/IP,SOCKET
- 苹果3D视觉报告:龙头引领行业大趋势
- echarts地图
- UNIX网络编程之IO复用(一):select系统调用
- 任务列表(360公司2017春招真题)
- What does [B >: A] do in Scala?
- One or more constraints have not been satisfied.
- 5.Schema与数据类型优化
- 设计资源管理类时应注意的细节
- Leetcode c语言-Swap Nodes in Pairs
- 计算机体系结构(一)
- 文章标题