2012-02-23 216 views
1

所以我完全失去了它,当有人使用select()像我展示了一些代码:SOCKET文件描述

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集中,0描述符(标准输入)显然消失。

谁能解释这件事?我不觉得这是正确的,但我不能真正弄清楚。也许再次设置一些特定的FD设置是一种实际的机制...

我认为bind()listen()可以修改fd集以某种方式。我设置了几个断点,并检查输出。随后,FD集没有改变。

UPDATE:

真正让我困惑的是第二FD_ZERO(&readfds)。 显然,第一个就像在缓冲区中清理生锈的东西。在每次迭代中,我们必须将fdset清除为未来的默认值。我只是不理解第二个。要么是错误的,要么不会伤害到任何人。

+1

'select'会改变fdset,但'bind'和'listen'不能,它们甚至没有指向它的指针。但是请自己帮忙,并使用像'poll'或'epoll'这样的现代API,并且不要再担心fdset。 – 2012-02-23 03:18:23

+0

听起来很酷,但我不能得到它 – jasonkim 2012-02-23 03:20:57

+1

使用'民意测验'。它现代,便携和快速。 'epoll'仅用于基准自我愉悦,它擅长的基准测试不符合大多数真实世界的使用需求(其中'epoll'实际上比'poll'慢得多)。 – 2012-02-23 03:50:41

回答

4

不知道从哪里你的困惑所在,但这里的一个解释。

的fdset是从0开始索引文件描述符位掩码(在技术上,我不认为它是一个位掩码,但任何其他的实现是......怪)。

因此,一个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一个选择调用将返回。传它作为读取fdset意味着如果你能够读取套接字或者在标准输入中显示出某些内容(例如使用键盘),就会返回。

这可能对代码很有用“聊天”的应用,因为它会等待从你或你的朋友在另一端输入。

你之所以公顷已经重新调零并重新设置这些位中的fdset是因为select本身修改所述一组,以指示什么FD(或FDS)它检测到的动作。

示例:如果有东西通过套接字进入,而没有通过标准输入进入,则fdset将被修改select以仅设置该位。这样你就可以用FD_ISSET来检测你应该看哪个fds。


如果,你似乎在注释中指出,有两个FD_ZERO()/FD_SET()序列之间(使用readfds或其它呼叫),则没有select电话,是的,看来首先是不必要的,因为信息将被第二个覆盖。

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

+0

让我感到困惑的是代码实际上很清晰,并且自己读了两次。 – jasonkim 2012-02-23 03:16:45

+0

@ y26jin,这是因为'select'修改了数组 - 我添加了答案来扩展它。 – paxdiablo 2012-02-23 03:24:23

+0

我的意思是,第二个在select()修改任何东西之前被调用。 – jasonkim 2012-02-23 03:26:58

1

Select()用于当您试图同时侦听多个套接字时。每当你接受()一个套接字连接时,一个套接字描述符被返回,你用它来发送/接收文件。

当你做一个FD_SET你添加一个套接字描述符(它可能是读/写)。 FD_ZERO清除该特定集合中的所有条目。

因此,基本上每次接受连接时都可以将套接字描述符添加到套件中(即如果要使用该套接字来读/写)。

当您调用select()函数时,您可以指定要使用的集合。 (例如:readfds)和select()轮询所有已经在该组中的套接字(readfds)。

欲了解更多信息,请阅读beej's guide to network programing。它是一个非常好的教程来学习。

0

select(2)修改它的参数fd集,所以你应该在每次迭代时重新初始化它们。