创建隧道时需要 "maxfd" 什么?
What is the need for "maxfd" when creating a tunnel?
在此 link、https://backreference.org/2010/03/26/tuntap-interface-tutorial/ 中,有一个使用 tun/tap 接口创建 TCP 隧道的代码示例,如下所示。
/* net_fd is the network file descriptor (to the peer), tap_fd is the
descriptor connected to the tun/tap interface */
/* use select() to handle two descriptors at once */
maxfd = (tap_fd > net_fd)?tap_fd:net_fd;
while(1) {
int ret;
fd_set rd_set;
FD_ZERO(&rd_set);
FD_SET(tap_fd, &rd_set); FD_SET(net_fd, &rd_set);
ret = select(maxfd + 1, &rd_set, NULL, NULL, NULL);
if (ret < 0 && errno == EINTR) {
continue;
}
if (ret < 0) {
perror("select()");
exit(1);
}
if(FD_ISSET(tap_fd, &rd_set)) {
/* data from tun/tap: just read it and write it to the network */
nread = cread(tap_fd, buffer, BUFSIZE);
/* write length + packet */
plength = htons(nread);
nwrite = cwrite(net_fd, (char *)&plength, sizeof(plength));
nwrite = cwrite(net_fd, buffer, nread);
}
if(FD_ISSET(net_fd, &rd_set)) {
/* data from the network: read it, and write it to the tun/tap interface.
* We need to read the length first, and then the packet */
/* Read length */
nread = read_n(net_fd, (char *)&plength, sizeof(plength));
/* read packet */
nread = read_n(net_fd, buffer, ntohs(plength));
/* now buffer[] contains a full packet or frame, write it into the tun/tap interface */
nwrite = cwrite(tap_fd, buffer, nread);
}
}
该代码摘录中 "maxfd" 的用途是什么?确切的行是:
maxfd = (tap_fd > net_fd)?tap_fd:net_fd;
ret = select(maxfd + 1, &rd_set, NULL, NULL, NULL);
这是危险且过时的 select
函数工作方式的产物。它需要一个参数,该参数限制了传递给它的 fd_set
对象的大小(以位为单位),并且不能使用大于 FD_SETSIZE
施加的任意限制的 fd 数字。如果您未能满足这些要求,则会产生未定义行为。
无论您在哪里看到 select
,您都应该将其替换为 poll
,它不受这些限制,具有更易于使用的界面和更多功能。
在此 link、https://backreference.org/2010/03/26/tuntap-interface-tutorial/ 中,有一个使用 tun/tap 接口创建 TCP 隧道的代码示例,如下所示。
/* net_fd is the network file descriptor (to the peer), tap_fd is the
descriptor connected to the tun/tap interface */
/* use select() to handle two descriptors at once */
maxfd = (tap_fd > net_fd)?tap_fd:net_fd;
while(1) {
int ret;
fd_set rd_set;
FD_ZERO(&rd_set);
FD_SET(tap_fd, &rd_set); FD_SET(net_fd, &rd_set);
ret = select(maxfd + 1, &rd_set, NULL, NULL, NULL);
if (ret < 0 && errno == EINTR) {
continue;
}
if (ret < 0) {
perror("select()");
exit(1);
}
if(FD_ISSET(tap_fd, &rd_set)) {
/* data from tun/tap: just read it and write it to the network */
nread = cread(tap_fd, buffer, BUFSIZE);
/* write length + packet */
plength = htons(nread);
nwrite = cwrite(net_fd, (char *)&plength, sizeof(plength));
nwrite = cwrite(net_fd, buffer, nread);
}
if(FD_ISSET(net_fd, &rd_set)) {
/* data from the network: read it, and write it to the tun/tap interface.
* We need to read the length first, and then the packet */
/* Read length */
nread = read_n(net_fd, (char *)&plength, sizeof(plength));
/* read packet */
nread = read_n(net_fd, buffer, ntohs(plength));
/* now buffer[] contains a full packet or frame, write it into the tun/tap interface */
nwrite = cwrite(tap_fd, buffer, nread);
}
}
该代码摘录中 "maxfd" 的用途是什么?确切的行是:
maxfd = (tap_fd > net_fd)?tap_fd:net_fd;
ret = select(maxfd + 1, &rd_set, NULL, NULL, NULL);
这是危险且过时的 select
函数工作方式的产物。它需要一个参数,该参数限制了传递给它的 fd_set
对象的大小(以位为单位),并且不能使用大于 FD_SETSIZE
施加的任意限制的 fd 数字。如果您未能满足这些要求,则会产生未定义行为。
无论您在哪里看到 select
,您都应该将其替换为 poll
,它不受这些限制,具有更易于使用的界面和更多功能。