Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么FD#u ISSET()要在接受前进行判断();建立连接_C_Sockets - Fatal编程技术网

C 为什么FD#u ISSET()要在接受前进行判断();建立连接

C 为什么FD#u ISSET()要在接受前进行判断();建立连接,c,sockets,C,Sockets,今天我刚刚学习了套接字的select()。互联网上的信息直接表明,FD_ISSET()判断FD是否可用,如果可用,accept()建立连接 但是没有解释为什么不能先与accept()建立连接,然后使用FD\u ISSET()确定FD是否可用 我的猜测是,使用accept()建立连接比使用FD\u ISSET()确定FD是否可用要消耗更多的资源。对于侦听套接字,套接字应该是读取fds的一部分select()将被唤醒select()将返回实际可读的read\u fds子集 如果侦听套接字是该子集的一

今天我刚刚学习了套接字的
select()
。互联网上的信息直接表明,
FD_ISSET()
判断FD是否可用,如果可用,
accept()
建立连接

但是没有解释为什么不能先与
accept()
建立连接,然后使用
FD\u ISSET()
确定FD是否可用


我的猜测是,使用
accept()
建立连接比使用
FD\u ISSET()
确定FD是否可用要消耗更多的资源。

对于侦听套接字,套接字应该是
读取fds
的一部分<如果侦听套接字可读,则code>select()将被唤醒
select()
将返回实际可读的
read\u fds
子集


如果侦听套接字是该子集的一部分,那么它是可读的,这表示新连接已准备好接受。对于TCP,这通常意味着三方握手已经完成。因此,侦听套接字上的
accept()
将返回一个新套接字以表示新连接。

对于侦听套接字,该套接字应该是
读取fds的一部分<如果侦听套接字可读,则code>select()
将被唤醒
select()
将返回实际可读的
read\u fds
子集


如果侦听套接字是该子集的一部分,那么它是可读的,这表示新连接已准备好接受。对于TCP,这通常意味着三方握手已经完成。因此,侦听套接字上的
accept()
将返回一个新套接字来表示新连接。

Linux手册页以以下方式描述
select()
函数:

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
select()允许程序监视多个文件描述符, 等待,直到一个或多个文件描述符为 某种类型的I/O操作(例如,可能的输入)。档案 如果可以执行 相应的I/O操作(例如,读取(2)或足够小的 不阻塞地写入(2)

select()
的目标是允许您测试一个或多个套接字是否准备好执行操作。
timeout
参数允许您指定任何套接字准备就绪的等待时间。因此,这是一个同步调用,您调用该函数,它将在一个或多个套接字准备好执行操作时返回,或者,如果指定了超时值,则在超时过期时返回

成功后,select()和pselect()返回文件的编号 包含在三个返回描述符集中的描述符(即, 在READFD、WRITEFD、READFD中设置的位的总数, 例外情况)。如果超时过期,则返回值可能为零 在任何文件描述符准备就绪之前

在出现错误时,返回-1,并设置errno以指示错误;这个 文件描述符集未修改,超时变得未定义

通过使用
FD\u SET()
宏指定映射,可以指定要由
select()
检查的套接字。有关示例,请参见以及和

如果在一个掩码中设置了多个套接字,或者正在使用多个设置了套接字的掩码,那么当
select()
函数返回指示一个或多个套接字已就绪时,需要使用
FD_ISSET()
宏来确定您请求状态的套接字中的哪些实际上已就绪

但是,如果您仅在一个掩码中指定了一个套接字,那么当
select()
返回指示套接字已就绪时,您只有一个套接字可以就绪

无论如何,使用
FD_ISSET()
的原因只是为了检查。将其视为良好的编程实践,以及在将来可能添加其他套接字的维护中提高源代码的健壮性

如果使用阻塞侦听套接字调用
accept()
,并且没有等待接受的连接,则线程将阻塞
accept()
,直到收到连接请求

如果队列上不存在挂起的连接,并且套接字 accept()未标记为非阻塞,它会阻塞调用方,直到 连接已存在。如果插座标记为非阻塞和否 队列上存在挂起的连接,accept()失败,错误为 EAGAIN或EWOOLDLOCK错误

为了得到套接字上传入连接的通知,您可以 使用select(2)、poll(2)或epoll(7)。将显示一个可读的事件 在尝试新连接时传递,然后您可以调用 accept()获取该连接的套接字。或者,你可以 设置套接字以在套接字上发生活动时传递SIGIO;看见 有关详细信息,请参阅插座(7)


由于您正在使用
select()
检查侦听套接字是否准备就绪,最有可能的行为是使用
accept()
块不是您想要的行为,因此在调用
accept()
之前先使用
FD_ISSET()
似乎是最谨慎的操作过程。

select()以这种方式工作:

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
select()允许程序监视多个文件描述符, 等待,直到一个或多个文件描述符为 某种类型的I/O操作(例如,可能的输入)。档案 如果可以执行 相应的I/O操作(例如,读取(2)或足够小的 不阻塞地写入(2)

select()
的目标是允许您测试一个或多个套接字是否准备好执行操作。
超时
参数al