[求助] c++ 使用 "select" 不能监测到可读的 socket

2021-03-23 13:33:31 +08:00
 vcfghtyjc

我在使用 c++ 的 select 实现服务器同时连接多个客户端,出现的情况是有的时候 FD_ISSET 可以监测处哪些 socket 可读,有的时候虽然所有 socket 用 FD_ISSET 都返回 0,但是客户端是发送了数据过来的。如果读取 socket,是可以读到客户端发的内容,但是 FD_ISSETselect 函数并不会标记该 socket 为可读。

当我用多个客户端和服务器向服务器发信息的时候,一般是前几次所有 socket 都可以正常检测出可读的 socket,逐渐的,可检测出的可读 socket 越来越少,直到所有 socket 都被认为是不可读。

不知道有没有哪位大佬知道原因。我现在用 macOS 写代码,调用的并不是 FD_ISSET 而是 __DARWIN_FD_ISSET,不知道和这个有没有关系。

顺便问一下,FD_ISSET 的值是什么时候更新的?我在读 socket 前后各返回了 FD_ISSET,返回的是相同的值(该值表示 socket 可读)。所以是在执行 select 时候更新的吗?

1015 次点击
所在节点    问与答
9 条回复
togou
2021-03-23 18:37:20 +08:00
用 epoll 吧 select 虽然每个系统都有 但是 现在几乎不怎么用了
vcfghtyjc
2021-03-23 23:39:42 +08:00
@togou 谢谢,我试试。主要是 epoll 在 mac 上没有,就用了 select
byaiu
2021-03-24 09:05:55 +08:00
这个 set 每次都要设置一下吧……是不是只在循环开始设置过?
vcfghtyjc
2021-03-24 09:10:05 +08:00
@byaiu 你是指 `FD_SET` 吗?每次 `select` 之前都要重新设置吗?我没有重新设置,前面几次 `select` 都没什么问题,后面才出现的问题。
byaiu
2021-03-24 10:12:06 +08:00
@vcfghtyjc 这个还是要重新设置的。你可以试试看。
vcfghtyjc
2021-03-24 12:14:20 +08:00
@byaiu 嗯,解决了,没太想懂为什么每次都要 set,感觉这里效率有点低,代码有些冗长。
byaiu
2021-03-24 13:02:45 +08:00
效率并不低。这个是 bit pattern,印象里只有监听超过 1024 个 fd 的时候才会不够用。一般的程序用不到这么多的客户端。

传来传去的问题在 epoll 里得到了解决,但是也是得一个 fd 一个 fd 的 set 到内核里去,对于少量 fd ( 10 个的量级),select 还有可能是最高效的。
byaiu
2021-03-24 13:05:04 +08:00
@vcfghtyjc 系统层面的编程,需要的是用户层适配,而不是质疑系统层面的 API 设计。这些历史遗留问题也不是现在就能解决掉的了。

好在,这种问题只需要解决一次,真正的价值还是用户层的程序实现的。
vcfghtyjc
2021-03-25 00:09:38 +08:00
@byaiu 学到了,多谢!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/764234

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX