Unix中的函数select和poll用来,支持Unix中I/O复用的功能,在Unix中I/O模型可以分为以一几种:
(1)阻塞I/O
(2)非阻塞I/O
(3)I/O复用(select和poll)
(4)信号驱动I/O(SIGIO)
(5)异步I/O
其中,现在比较流行的I/O模型是阻塞I/O模型.阻塞I/O是当应用程序和内核交换数据时,由于内核还没有准备好数据,那么应用程序必须进行阻塞,不能继续执行,直到内核的数据准备好!应用程序取到数据返回后,阻塞过程结束!但返回的结果也并不一定是正确的!这里只是举一个简单的例子!也许情况会更加的复杂!
非阻塞I/O,例如在和内核交换数据时,如果内核的数据没有准备好,那么应用程序不会一真等待,会有一个返回信息,以判断是那里出了问题!这样有助于确认是在那个阶段出了问题!
I/O复用,我们就可以调用系统调用select和poll!在这两个系统调用中的某一个阻塞,而不是真正的阻塞I/O系统调用!
下面主要介绍I/O复用中的select函数!select函数可以指示内核等待多个事件中的任一个发生,仅在一个或多个事件发生,或者等待一个足够的时间后才唤醒进程!select函数的原型如下:Unix中的函数select和poll用来,支持Unix中I/O复用的功能,在Unix中I/O模型可以分为以一几种:
(1)阻塞I/O
(2)非阻塞I/O
(3)I/O复用(select和poll)
(4)信号驱动I/O(SIGIO)
(5)异步I/O
其中,现在比较流行的I/O模型是阻塞I/O模型.阻塞I/O是当应用程序和内核交换数据时,由于内核还没有准备好数据,那么应用程序必须进行阻塞,不能继续执行,直到内核的数据准备好!应用程序取到数据返回后,阻塞过程结束!但返回的结果也并不一定是正确的!这里只是举一个简单的例子!也许情况会更加的复杂!
非阻塞I/O,例如在和内核交换数据时,如果内核的数据没有准备好,那么应用程序不会一真等待,会有一个返回信息,以判断是那里出了问题!这样有助于确认是在那个阶段出了问题!
I/O复用,我们就可以调用系统调用select和poll!在这两个系统调用中的某一个阻塞,而不是真正的阻塞I/O系统调用!
下面主要介绍I/O复用中的select函数!select函数可以指示内核等待多个事件中的任一个发生,仅在一个或多个事件发生,或者等待一个足够的时间后才唤醒进程!select函数的原型如下:
#include <sys/types.h>
#include<sys/time.h>
int select (int maxfdp1,fd_set *readset,fd_set * writeset,fd_set excpetset,const struct timeval *timeout);
返回值:准备好的描述符的正数目 0---超时 -1---出错!
其中最后一个参数是一个结构体的指针,它表示等待内核中的一组描述符任一个准备好需要花费多久的时间!其中timeval指定了秒数和微秒数。
struct timeval{
long tv_sec;//秒数
long tv_usec;//微秒数
};
将 timeout设置为空指针时,会永远等待下去,等待固定的时间:如果timeout指向的timeval中的具体的值时,会等待一个固定的时间,不等待立刻返回,这时timeval中的tv_sec和tv_usec为0.
select有三个可能的返回值。
1.正常情况下返回就绪的文件描述符个数;
2.经过了timeout时长后仍无设备准备好,返回值为0;
3.如果select被某个信号中断,它将返回-1并设置errno为EINTR。
4.如果出错,返回-1并设置相应的errno。
EBADF 文件描述词为无效的或该文件已关闭
EINTR 此调用被信号所中断
EINVAL 参数n 为负值。
ENOMEM 核心内存不足
中间的三个参数readset writeset和excpetset指定我们要让内核测试读、写、异常条件所需的描述字!函数select使用描述字集,它一般是一个整型的数组,每个数中的每一位代表一个描述符!
系统提供了4个宏对描述符集进行操作:
#include <sys/select.h>
#include <sys/time.h>
//设置文件描述符集fdset中对应于文件描述符fd的位
void FD_SET(int fd, fd_set *fdset);
//清除文件描述符集fdset中对应于文件描述符fd的位(设置为0)
void FD_CLR(int fd, fd_set *fdset);
//清除文件描述符集fdset中的所有位(既把所有位都设置为0)
void FD_ZERO(fd_set *fdset);
//在调用select后使用FD_ISSET来检测文件描述符集fdset中对应于文件描述符fd的位是否被设置。
void FD_ISSET(int fd, fd_set *fdset);
(1)阻塞I/O
(2)非阻塞I/O
(3)I/O复用(select和poll)
(4)信号驱动I/O(SIGIO)
(5)异步I/O
其中,现在比较流行的I/O模型是阻塞I/O模型.阻塞I/O是当应用程序和内核交换数据时,由于内核还没有准备好数据,那么应用程序必须进行阻塞,不能继续执行,直到内核的数据准备好!应用程序取到数据返回后,阻塞过程结束!但返回的结果也并不一定是正确的!这里只是举一个简单的例子!也许情况会更加的复杂!
非阻塞I/O,例如在和内核交换数据时,如果内核的数据没有准备好,那么应用程序不会一真等待,会有一个返回信息,以判断是那里出了问题!这样有助于确认是在那个阶段出了问题!
I/O复用,我们就可以调用系统调用select和poll!在这两个系统调用中的某一个阻塞,而不是真正的阻塞I/O系统调用!
下面主要介绍I/O复用中的select函数!select函数可以指示内核等待多个事件中的任一个发生,仅在一个或多个事件发生,或者等待一个足够的时间后才唤醒进程!select函数的原型如下:
#include <sys/types.h>
#include<sys/time.h>
int select (int maxfdp1,fd_set *readset,fd_set * writeset,fd_set excpetset,const struct timeval *timeout);
返回值:准备好的描述符的正数目 0---超时 -1---出错!
其中最后一个参数是一个结构体的指针,它表示等待内核中的一组描述符任一个准备好需要花费多久的时间!其中timeval指定了秒数和微秒数。
struct timeval{
long tv_sec;//秒数
long tv_usec;//微秒数
};
将 timeout设置为空指针时,会永远等待下去,等待固定的时间:如果timeout指向的timeval中的具体的值时,会等待一个固定的时间,不等待立刻返回,这时timeval中的tv_sec和tv_usec为0.
select有三个可能的返回值。
1.正常情况下返回就绪的文件描述符个数;
2.经过了timeout时长后仍无设备准备好,返回值为0;
3.如果select被某个信号中断,它将返回-1并设置errno为EINTR。
4.如果出错,返回-1并设置相应的errno。
EBADF 文件描述词为无效的或该文件已关闭
EINTR 此调用被信号所中断
EINVAL 参数n 为负值。
ENOMEM 核心内存不足
中间的三个参数readset writeset和excpetset指定我们要让内核测试读、写、异常条件所需的描述字!函数select使用描述字集,它一般是一个整型的数组,每个数中的每一位代表一个描述符!
系统提供了4个宏对描述符集进行操作:
#include <sys/select.h>
#include <sys/time.h>
//设置文件描述符集fdset中对应于文件描述符fd的位
void FD_SET(int fd, fd_set *fdset);
//清除文件描述符集fdset中对应于文件描述符fd的位(设置为0)
void FD_CLR(int fd, fd_set *fdset);
//清除文件描述符集fdset中的所有位(既把所有位都设置为0)
void FD_ZERO(fd_set *fdset);
//在调用select后使用FD_ISSET来检测文件描述符集fdset中对应于文件描述符fd的位是否被设置。
void FD_ISSET(int fd, fd_set *fdset);
#include <sys/types.h>
#include<sys/time.h>
int select (int maxfdp1,fd_set *readset,fd_set * writeset,fd_set excpetset,const struct timeval *timeout);
int select (int maxfdp1,fd_set *readset,fd_set * writeset,fd_set excpetset,const struct timeval *timeout);
返回值:准备好的描述符的正数目 0---超时 -1---出错!
其中最后一个参数是一个结构体的指针,它表示等待内核中的一组描述符任一个准备好需要花费多久的时间!其中timeval指定了秒数和微秒数。
struct timeval{
long tv_sec;//秒数
long tv_usec;//微秒数
};
将 timeout设置为空指针时,会永远等待下去,等待固定的时间:如果timeout指向的timeval中的具体的值时,会等待一个固定的时间,不等待立刻返回,这时timeval中的tv_sec和tv_usec为0.
select有三个可能的返回值。
1.正常情况下返回就绪的文件描述符个数;
2.经过了timeout时长后仍无设备准备好,返回值为0;
3.如果select被某个信号中断,它将返回-1并设置errno为EINTR。
4.如果出错,返回-1并设置相应的errno。
2.经过了timeout时长后仍无设备准备好,返回值为0;
3.如果select被某个信号中断,它将返回-1并设置errno为EINTR。
4.如果出错,返回-1并设置相应的errno。
EBADF 文件描述词为无效的或该文件已关闭
EINTR 此调用被信号所中断
EINVAL 参数n 为负值。
ENOMEM 核心内存不足
中间的三个参数readset writeset和excpetset指定我们要让内核测试读、写、异常条件所需的描述字!函数select使用描述字集,它一般是一个整型的数组,每个数中的每一位代表一个描述符!
EINTR 此调用被信号所中断
EINVAL 参数n 为负值。
ENOMEM 核心内存不足
中间的三个参数readset writeset和excpetset指定我们要让内核测试读、写、异常条件所需的描述字!函数select使用描述字集,它一般是一个整型的数组,每个数中的每一位代表一个描述符!
系统提供了4个宏对描述符集进行操作:
#include <sys/select.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/time.h>
//设置文件描述符集fdset中对应于文件描述符fd的位
void FD_SET(int fd, fd_set *fdset);
void FD_SET(int fd, fd_set *fdset);
//清除文件描述符集fdset中对应于文件描述符fd的位(设置为0)
void FD_CLR(int fd, fd_set *fdset);
void FD_CLR(int fd, fd_set *fdset);
//清除文件描述符集fdset中的所有位(既把所有位都设置为0)
void FD_ZERO(fd_set *fdset);
//在调用select后使用FD_ISSET来检测文件描述符集fdset中对应于文件描述符fd的位是否被设置。
void FD_ISSET(int fd, fd_set *fdset);
void FD_ISSET(int fd, fd_set *fdset);
下面是select函数的一个例子,主要参考网上的例子,并进行的适当的改变!并增加了客户端的程序。修改fd[i]数组,可是实现动态的管理,也解决了,当一个客户不断的断开再连接时,服务器也断开的情况。