(一)fd_set 的实现
fd_set是一组文件描述字(fd)的集合。 UNIX系统在头文件<sys/select.h>中定义常量FD_FD_SETSIZE,它是数据类型fd_set的描述字数量,其值通常是1024,这样就能表示<1024的fd(fd的最大值必须<FD_SETSIZE),先介绍一下fd_set的实现过程。
define FD_SETSIZE 1024
typedef unsigned long fd_mask;
#define NBBY 8 /* number of bits in a byte */
#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
#define howmany(x, y) (((x) + ((y) - 1)) / (y))
typedef struct fd_set
{
fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
} fd_set;
#define _fdset_mask(n) ((fd_mask)1 << ((n) % NFDBITS))
#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= _fdset_mask(n))
#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~_fdset_mask(n))
#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & _fdset_mask(n))
#define FD_COPY(f, t) bcopy(f, t, sizeof(*(f)))
#define FD_ZERO(p) bzero(p, sizeof(*(p)))
(二)fd_set的用法
FD_ZERO(fd_set *fdset);//将指定的文件描述符集清空,在对文件描述符集合进行设置前,必须对其进行初始化,如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的。
FD_SET(fd_set *fdset);用于在文件描述符集合中增加一个新的文件描述符。
FD_CLR(fd_set *fdset);用于在文件描述符集合中删除一个文件描述符。
FD_ISSET(int fd,fd_set *fdset);用于测试指定的文件描述符是否在该集合中。
(三)fd_set 应用模型
static int Func()
{
int i = 0;
int rv = -1;
fd_set readfds;//读集合
fd_set writefds;//写集合
struct timeval tv;
struct timeval *tvp;
tv.tv_sec = 1;
tv.tv_usec = 0;
tvp = &tv;
while (1)
{
FD_ZERO(&readfds);//清空集合
FD_ZERO(&writefds);
FD_SET(tcp_sock, &readfds);//加入服务器集合
for (i = 0; i < MAX_CLIENTS; i++)
{
if (-1 != client_array[i].sock)
{
FD_SET(client_array[i].sock, &readfds);//加入客户端集合
}
}
rv = select(FD_SETSIZE, &readfds, &writefds, NULL, tvp);
if (rv < 0)
{
continue;
}
if (FD_ISSET(tcp_sock, &readfds))
{
deal_connect(PORT_NMP);
}
for (i=0; i<MAX_CLIENTS; i++)
{
if (client_array[i].sock != -1 && FD_ISSET(client_array[i].sock, &readfds))
{
deal_request(&client_array[i]);
}
}
}
}