因此,当有人使用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()
的其他调用),那么是的,似乎第一个是不必要的,因为该信息将被第二个覆盖。没有看到完整的代码或建筑设计文档:-),这很难分辨。