基于select的多客户端转发服务器报Bad file descriptor错误原因咨询
"select: Bad file descriptor"错误根源分析及解决
错误根源
fd_set是存储文件描述符位掩码的结构体,未初始化的fd_set会包含随机的垃圾位值。你代码中定义fd_set base_rdset;后,直接调用FD_SET(socket_fd, &base_rdset)仅会将监听socket对应的位设为1,但结构体中其他位仍保留随机的0或1状态。
当select被调用时,会检查rdset(从base_rdset拷贝而来)中所有置位的文件描述符。如果这些随机置位的位对应无效的文件描述符(比如从未打开的、已关闭的fd),select就会触发EBADF错误,即"Bad file descriptor"。
出现“有时正常有时报错”的原因,完全取决于未初始化base_rdset的随机位状态:若随机置位的都是有效fd或无额外置位,程序正常运行;若随机置位了无效fd,则直接触发错误。
解决原理
添加FD_ZERO(&base_rdset)语句后,会将base_rdset的所有位清零,之后调用FD_SET(socket_fd, &base_rdset)仅会将监听socket对应的位设为1,其余位均为0。此时select检查的所有文件描述符都是有效的,自然不会再触发错误。
代码修正点
必须在初始化base_rdset时先清零:
fd_set base_rdset; fd_set rdset; FD_ZERO(&base_rdset); // 先清空所有位,避免随机无效fd干扰 FD_SET(socket_fd, &base_rdset);
额外说明
- 你当前在循环内对
rdset先清零再拷贝base_rdset的逻辑是正确的,符合select的使用规范 - 客户端断开时调用
FD_CLR从base_rdset移除对应fd的处理逻辑无误
内容的提问来源于stack exchange,提问作者siyuan wang
相关产品推荐
相关产品推荐

