因此,当有人使用select()向我展示一些代码时,我完全失去了它:

FD_ZERO(&readfds);
FD_SET(socket,&readfds);
FD_SET(0,&readfds);
.......// bind() and listen(),regular stuff
// Before select(),this guy cleared readfds to null and sort of start all over again
FD_ZERO(&readfds);// Behold,this is exactly the line confusing myself
FD_SET(socket,&readfds);
// select will be called in the future within a infinite loop

因此,基本上说绑定(bind)和监听之后的FD_ZERO是出于某种原因清除了先前的内容,然后再次将套接字文件描述符插入到fd集合中。同时,在fd集合中,0描述符(标准输入)显然消失了。

谁能解释整个事情?我不认为这是正确的,但我无法真正弄清楚。也许重新设置一些特定的fd集是一种实用的机制...

我以为bind()listen()可以某种方式修改fd set。我设置了几个断点并检查了输出。因此,fd set完全没有变化。

更新:

真正让我感到困惑的是第二个FD_ZERO(&readfds)
显然,第一个就像清除缓冲区中的生锈东西。在每次迭代中,我们都必须将fdset清除为默认值,以备将来使用。我只是不明白第二个。要么这是错的,要么不会造成任何伤害。

最佳答案

不知道您的困惑在哪里,但这是一个解释。

fdset是从零开始索引的文件描述符的位掩码(从技术上讲,我不认为它必须是位掩码,但是任何其他实现方式都可能会很奇怪。)。

因此,fdset可能类似于:

              Byte 0                              Byte 1
+---+---+---+---+---+---+---+---+ +---+---+----+----+----+----+----+----+
|fd0|fd1|fd2|fd3|fd4|fd5|fd6|fd7| |fd8|fd9|fd10|fd11|fd12|fd13|fd14|fd15|
+---+---+---+---+---+---+---+---+ +---+---+----+----+----+----+----+----+

想法是如果您对给定的fd(文件描述符)设置该位。如果您对它不感兴趣,则无需赘述。
FD_ZERO将清除所有位,这是一个很好的起点。然后,这两个FD_SET调用将设置fd0(标准输入)和fd<socket>的位。

然后,如果对标准输入有操作或对套接字有操作,则使用该fdset的select调用将返回(操作的类型取决于将fdset传递给select时使用的参数位置。将其作为read fdset传递意味着如果您可以读取套接字或标准输入(例如您使用键盘)上显示的内容,则将返回该值。

这在“聊天”应用程序的代码中可能很有用,因为它将等待另一端您或您的 friend 的输入。

之所以必须将fdset中的位重新清零并重新设置,是因为select本身会修改该集以指示它检测到操作的fd(或fds)。

例如:如果有什么东西是通过套接字传入的,而没有通过标准输入传入的,则fdset将被select修改为仅设置该位。这样,您可以使用FD_ISSET来检测应该查看的fds。

如您似乎在注释中指出的那样,如果两个select序列之间没有readfds调用(或使用FD_ZERO()/FD_SET()的其他调用),那么是的,似乎第一个是不必要的,因为该信息将被第二个覆盖。

没有看到完整的代码或建筑设计文档:-),这很难分辨。

10-08 08:10