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