目前,在我的学位课程中,我们开始使用套接字。
关于轮询输入的轮询,我有几个问题,
使用select()函数。
int select( int nfds,
fd_set *readfds,
fd_set *writefds,
fd_set *exceptfds,
const struct timespec *timeout);
我们给select" nfds" param,通常会 是我们想要监控的最大套接字号。我怎样才能只观看一个特定的插座而不是 0到nfds_val 插座的范围?
我们使用的文件描述符对象是什么?他们的目的是什么, 为什么我们不能指出"选择"到相关的套接字结构?
我已经在论坛上阅读了有关阻止和非阻止模式的选择,但无法理解其含义或用途如果有人能够解释,那么每个人,以及如何实施这些,都会很高兴。
最后但并非最不重要(仅限暂时:D) - 将socketaddr_in绑定到套接字号时,为什么需要转换为 socketaddr * 而不是将其保留为< strong> sockaddr_in * ? 我的意思是除了 bind 方法需要这种指针类型的事实;)
非常感谢一些专家在这里的回答:)
谢谢你们,祝你们度过愉快的一周!
答案 0 :(得分:2)
我们给出选择“nfds”param,这通常是我们想要监视的最大套接字号。我怎样才能只观察一个特定的套接字而不是0到nfds_val套接字的范围?
编辑。(抱歉,此前的文字错误)只需提供套接字descriptor + 1
即可。我很确定这并不意味着操作系统会检查[0, 1... descriptor]
范围内的所有描述符。
我们使用的文件描述符对象是什么?它们的目的是什么,为什么我们不能将“选择”指向相关的套接字结构?
文件描述符通常是OS给用户的整数值。操作系统使用描述符来控制物理和逻辑资源 - 一个文件描述符意味着操作系统为您提供了一些类似文件的来控制。由于Berkeley Sockets定义了读写操作,因此它们是类似文件的,而套接字对象本质上是纯文件描述符。
回答why can't we just point "select" to the relevant socket structure?
- 我们实际上可以。究竟要传递给select
的内容取决于操作系统和语言。在C中,您将套接字描述符(最可能是int
值)放入fd_set
。然后将fd_set
传递给select
。
修改强> Linux的一个小例子:
fd_set set;
FD_ZERO(&set);
FD_SET(socket_fd, &set);
// check if socket_fd is ready for reading
result = select(socket_fd + 1, &set, NULL, NULL, NULL);
if (result == -1) report_error(errno);
Docs.
Windows has similar code.
我已经阅读了论坛关于阻止和非阻止模式的选择,但无法理解每个模式的含义或用途,也不知道如何实现这些模式,如果有人能解释的话会很高兴。
阻止操作会使您的线程等待,直到完成为止。这是您使用的99%的功能。如果为某些IO准备好套接字,阻止select
将立即返回something
。它没有这样的套接字,线程会等待它们。 非阻止 select
,在后一种情况下,不会等待并返回-1
(错误)。
例如,尝试实现能够与多个客户端一起工作的单线程服务器,包括同时发生文件传输等长时间操作。在这种情况下,您绝对不希望使用阻塞套接字操作。
最后但并非最不重要(仅限暂时:D) - 将socketaddr_in绑定到套接字号时,为什么需要转换为socketaddr *而不将其保留为sockaddr_in *?我的意思是除了bind方法需要这种指针类型的事实;)
可能由于历史原因,但我不确定。 And there seems to be a fine answer on SO already.