!!!!!!!!!!!!
分类: LINUX
2009-05-21 16:01:26
【摘要】
本文主要说明select()在网络编程中的使用。
【关键词】
I/0复用,select()
一、问题的提出在网络编程中,我们经常需要处理多个I/O口或套接字,进程需要一种预先告知内核的能力,使得内核一旦发现进程指定一个或多个I/O条件就绪,它就通知进程,这种能力称为I/O复用,是由select()这个函数支持的,所以需要详细了解select()的使用。
二、解决思路I/O复用典型地用在下列网络应用场合:
n 当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/O复用。
n 一个客户同时处理多个套接口。
n 如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也是要用到I/O复用。
n 如果一个服务器既要处理TCP,又要处理UDP,一般也要使用I/O复用。
n 如果一个服务器要处理多个服务或者多个协议,一般要使用I/O复用。
函数说明
#include
#include
#include
Int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
函数说明 select()用来等待文件描述词状态的改变。参数n代表最大的文件描述词加1,参数readfds、writefds 和exceptfds 称为描述词组,是用来回传该描述词的读,写或例外的状况。
下面的宏提供了处理这三种描述词组的方式:
FD_CLR(int fd,fd_set* set);用来清除描述词组set中相关fd 的位
FD_ISSET(int fd,fd_set *set);用来测试描述词组set中相关fd 的位是否为真
FD_SET(int fd,fd_set*set);用来设置描述词组set中相关fd的位
FD_ZERO(fd_set *set);用来清除描述词组set的全部位参数
timeout为结构timeval,用来设置select()的等待时间,其结构定义如下
struct timeval
{
time_t tv_sec;
time_t tv_usec;
};
返回值:就绪描述字的正数目,0-超时,-1-出错。
该函数返回后,需要使用FD_ISSET宏来测试fd_set数据类型中的描述字。描述字集中任何与未就绪的描述字对应的位返回时均清0。为此,每次重新调用select()函数时,都得再次把所有描述字集中所关心的为均置1.
描述字就绪条件
1. 一个套接字准备好读的条件:
n 该套接口接收缓冲区中的数据字节数大于等于套接口接收缓冲区低潮标记的当前大小。对于这样的套接口的读操作将不阻塞并返回一个大于0的值(也就是返回准备好读入的数据)。
n 该连接的读这一半关闭(也就是接收FIN的TCP连接)。对这样的套接口的读操作将不阻塞并返回0(也就是返回EOF)。
n 该套接口是一个监听套接口且已完成的连接数不为0。对这样的套接口的accept通常不会阻塞。
n 其上有一个套接口错误待处理。对这样的套接口的读操作将不阻塞并返回-1(也就是返回一个错误),同时把errno设置成确切的错误条件。这些待处理的错误也可以通过指定SO_ERROR套接口选项调用getsockopt获得并清除。
2. 一个套接口准备好写的条件:
n 该套接口发送缓冲区的可用空间字节数大于等于套接口发送缓冲区低潮标记的当前大小,并且或者(1)该套接口已连接,或(2)该套接口不需要连接(例如udp套接口)。
n 该连接的写这一半关闭。对这样的套接口的写操作将产生SIGPIPE信号。
n 该套接口早先使用非阻塞式connect以建立连接,并且连接已经异步建立,或者connect已经失败告终。
n 其上有一个套接口错误待处理。对这样的套接口的写操作将不阻塞并返回-1,同时把errno设置成确切的错误条件。这些待处理的错误也可以通过指定SO_ERROR套接口选项调用getsockopt获取并清除。
3. 如果一个套接口存在带外数据或者仍处于待外标记,那么它有异常条件待处理。
注意:当某个套接口上发生错误时,它将有select标记为既可读又可写。