深入了解fd_set结构体在Linux中的使用方法 (fd_set结构体linux)
在Linux中,网络编程经常会涉及到fd_set结构体的使用。该结构体是操作系统提供的一种数据类型,主要用于描述一组文件描述符,可以在同一个数组中同时存放多个文件描述符。在本文中,我们将。
一、fd_set结构体的定义
fd_set结构体是Linux系统中的一个数据类型,定义在头文件中:
typedef struct fd_set {
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
} fd_set;
其中,__fd_mask和__FD_SETSIZE是系统定义的宏,__NFDBITS是一个数值常量。fds_bits数组是一个位向量,存放的是文件描述符的状态。
二、函数分析
1、FD_ZERO(fd_set *set)函数
FD_ZERO函数用于清空fd_set结构体的所有元素,即将每个元素都设置为0。函数原型如下:
int FD_ZERO(fd_set* set);
参数set是一个指向fd_set结构体的指针,返回值为0表示清空成功,-1表示失败。
2、FD_SET(int fd, fd_set *set)函数
FD_SET函数用于将文件描述符fd添加到fd_set结构体set中。函数原型如下:
void FD_SET(int fd, fd_set* set);
参数fd是待添加的文件描述符,set是指向保存文件描述符的fd_set结构体的指针。FD_SET函数将fd文件描述符添加到set中,以便进一步使用。如果fd失败或者已经存在于set中,将不做任何改变。
3、FD_CLR(int fd, fd_set *set)函数
FD_CLR函数用于将文件描述符fd从fd_set结构体set中删除。函数原型如下:
void FD_CLR(int fd, fd_set* set);
参数fd是待删除的文件描述符,set是指向保存文件描述符的fd_set结构体的指针。FD_CLR函数将fd文件描述符从set中删除,以便进一步使用。如果fd不在fd_set结构体中,FD_CLR函数将不做任何改变。
4、FD_ISSET(int fd, fd_set *set)函数
FD_ISSET函数用于判断文件描述符fd是否在fd_set结构体set中。函数原型如下:
int FD_ISSET(int fd, fd_set* set);
参数fd是待判断的文件描述符,set是指向保存了文件描述符的fd_set结构体的指针。FD_ISSET函数将会检测fd是否在set中,如果存在则返回1,不存在则返回0。
三、使用示例
为了更好地展示fd_set结构体的用法,我们在此列举一个简单的程序示例:
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 1024
#define LISTENQ 5
int mn(int argc, char **argv) {
int listenfd, connfd;
struct sockaddr_in servaddr, cliaddr;
socklen_t clilen;
char buf[MAXLINE];
int i, maxi, maxfd, sockfd;
int nready, client[FD_SETSIZE];
fd_set rset, allset;
/* 创建监听套接字 */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
/* 设置套接字地址重复利用 */
int optval = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof(int));
/* 绑定套接字地址 */
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(9938);
bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
/* 监听 */
listen(listenfd, LISTENQ);
maxfd = listenfd;
maxi = -1;
for (i = 0; i
client[i] = -1;
}
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
while (1) {
rset = allset;
nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
if (FD_ISSET(listenfd, &rset)) {
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
for (i = 0; i
if (client[i]
client[i] = connfd;
break;
}
}
if (i == FD_SETSIZE) {
fprintf(stderr, “too many clients”);
exit(1);
}
FD_SET(connfd, &allset);
if (connfd > maxfd) {
maxfd = connfd;
}
if (i > maxi) {
maxi = i;
}
if (–nready
continue;
}
}
for (i = 0; i
if ((sockfd = client[i])
continue;
}
if (FD_ISSET(sockfd, &rset)) {
if ((n = read(sockfd, buf, MAXLINE)) == 0) {
/* connection closed by client */
close(sockfd);
FD_CLR(sockfd, &allset);
client[i] = -1;
} else {
write(sockfd, buf, n);
}
if (–nready
break;
}
}
}
}
}
该程序实现了一个简单的echo服务器,其具体实现如下:
① 创建一个监听套接字。
② 绑定套接字地址。
③ 监听套接字。
④ 初始化一个fd_set结构体,将监听套接字添加到其中。
⑤ 循环调用select函数,等待连接请求或客户端数据,并进行相应的处理。