所以当有人使用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
所以基本上说绑定和监听之后的FD_ZERO
由于某种原因清楚了之前的内容并将套接字文件描述符再次插入到fd中。同时,在fd set中,0描述符(标准输入)显然已经消失了。 / p>
有人可以解释这一切吗?我不觉得这是正确的,但我真的无法弄明白。也许重新设置一些特定的fd设置是一种实用的机制......
我认为bind()
和listen()
可以某种方式修改fd。我设置了几个断点并检查输出。因此,fd set根本没有改变。< / p>
更新
真正令我困惑的是第二个FD_ZERO(&readfds)
。
显然,第一个就像在缓冲区中清除生锈的东西。在每次迭代中,我们必须将fdset清除为将来的默认值。我只是不明白第二个。无论是错误的还是无论如何都不会受到伤害。
答案 0 :(得分:4)
不确定你的困惑在哪里,但这是一个解释。
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
。将它作为读取fdset传递意味着如果您可以读取套接字或标准输入上显示的内容(例如您使用键盘),您将返回。
这可能对“聊天”应用程序的代码很有用,因为它会等待你或你朋友在另一端的输入。
你必须重新归零并重新设置fdset中的位的原因是因为select
本身修改了集合以指示它检测到动作的fd(或fds)。
示例:如果通过套接字传入某些内容而没有通过标准输入传入任何内容,则select
将修改fdset以仅设置该位。这样您就可以使用FD_ISSET
来检测您应该查看哪些fds。
如果您似乎在评论中指出,两个select
序列之间存在没有 readfds
次呼叫(或使用FD_ZERO()/FD_SET()
的其他呼叫) ,是的,似乎第一个是不必要的,因为信息将被第二个覆盖。
没有看到完整的代码或建筑设计文档:-),很难说。
答案 1 :(得分:1)
Select()
。每次你接受()一个套接字连接时,都会返回一个套接字描述符,你可以使用它来发送/接收文件。
当您执行FD_SET
时,您将套接字描述符添加到集合中(可能是读/写)。 FD_ZERO
清除该特定集合中的所有条目。
所以基本上每次接受连接时都可以将套接字描述符添加到集合中(即如果你想使用该套接字进行读/写)。
当您调用select()
功能时,您可以指定要使用的设置。 (例如:readfds)和select()
轮询该集合中已有的所有套接字(readfds)。
有关更多说明,请阅读beej's guide to network programing。这是一个非常好的学习教程。
答案 2 :(得分:0)
select(2)
修改了它的参数fd sets,所以你应该在每次迭代时重新初始化它们。