FD_SET,FD_ISSET的意思

合集下载

udp常用函数解析

udp常用函数解析

udp相关知识1.recvfrom函数解析#include <winsock.h>int PASCAL FAR recvfrom( SOCKET s, char FAR* buf, int len, int flags,struct sockaddr FAR* from, int FAR* fromlen);s:标识一个已连接套接口的描述字。

buf:接收数据缓冲区。

len:缓冲区长度。

flags:调用操作方式。

from:(可选)指针,指向装有源地址的缓冲区。

fromlen:(可选)指针,指向from缓冲区长度值例程:SOCKET sockSrv = socket(AF_INET,SOCK_DGRAM,0);char recvBuf[64];SOCKADDR_IN addrClient;int len = sizeof(SOCKADDR);BufSize = recvfrom(sockSrv , recvBuf,sizeof(recvBuf),0,(SOCKADDR*)&addrClient,&len);2.select 函数解析int select(int fds,fd_set* readfds,fd_set* writefds,fd_set* exceptfds,const struct timeval* timeout); fds:本参数忽略,仅起到兼容作用。

readfds:(可选)指针,指向一组等待可读性检查的套接口。

writefds:(可选)指针,指向一组等待可写性检查的套接口。

exceptfds:(可选)指针,指向一组等待错误检查的套接口。

timeout:select()最多等待时间,对阻塞操作则为NULL。

timeout为结构timeval,用来设置select()的等待时间,其结构定义如下struct timeval{time_t tv_sec; //second 秒time_t tv_usec; //microsecond 微妙};本函数用于确定一个或多个套接口的状态。

linux select区分读写

linux select区分读写

linux select区分读写Linux中的select函数是一个用于多路复用的系统调用,它可以同时监视多个文件描述符的状态,包括读、写和异常等事件。

在使用select函数时,我们可以通过设置相应的文件描述符集合来区分读和写。

首先,我们需要创建三个文件描述符集合:readfds、writefds和exceptfds。

readfds用于监视可读事件,writefds用于监视可写事件,exceptfds用于监视异常事件。

然后,我们需要将需要监视的文件描述符添加到相应的集合中。

对于需要监视读事件的文件描述符,我们可以使用FD_SET宏将其添加到readfds中;对于需要监视写事件的文件描述符,我们可以使用FD_SET宏将其添加到writefds中;对于需要监视异常事件的文件描述符,我们可以使用FD_SET宏将其添加到exceptfds中。

接下来,我们调用select函数,并传入最大文件描述符值加1、readfds、writefds和exceptfds作为参数。

select函数会阻塞程序执行,并等待指定的文件描述符集合中有事件发生。

当select函数返回时,我们可以通过检查相应的文件描述符集合来确定哪些文件描述符有可读或可写或异常事件发生。

对于每个文件描述符,在相应的集合中使用FD_ISSET宏进行检查即可。

如果返回值为真,则表示该文件描述符有相应类型的事件发生。

最后,我们可以根据检查结果进行相应处理。

例如,如果某个文件描述符在readfds中返回为真,则表示该文件描述符有可读事件发生,我们可以调用read函数来读取数据;如果某个文件描述符在writefds中返回为真,则表示该文件描述符有可写事件发生,我们可以调用write函数来写入数据;如果某个文件描述符在exceptfds中返回为真,则表示该文件描述符有异常事件发生,我们可以进行相应的处理。

总之,通过使用select函数和相应的文件描述符集合,我们可以区分读和写事件,并根据需要进行相应的处理。

select函数的返回值

select函数的返回值

select函数的返回值select函数是一种多路复用函数,它的作用是在多个文件描述符上等待IO事件发生。

具体来说,它可以在一组文件描述符上等待事件,这些事件可以是读、写或错误事件。

当其中任何一个文件描述符上发生了与它所感兴趣的事件相对应的事件,select函数就会返回。

这个返回值可以告诉我们发生了什么事件,从而让我们做出相应的处理。

select函数的返回值包含三个集合,分别是读、写和错误事件的文件描述符集合。

这些集合都是用结构体fd_set来表示的。

fd_set结构体定义如下:```c++typedef struct fd_set {unsigned long fds_bits[FD_SETSIZE / (8 * sizeof(unsigned long))];} fd_set;```其中,FD_SETSIZE 是一个预定义的常量,它表示一个 fd_set 中最多可以包含多少个文件描述符。

每个文件描述符都可以被 fd_set 中的一个 bit 位表示,fds_bits 数组就是用来保存这些位的。

在 select 函数调用完成后,我们可以通过对这三个集合进行操作,来获取文件描述符对应的事件是否发生。

具体来说,我们可以使用以下三个宏来操作 fd_set 结构体:- FD_ISSET(fd, &fdset):检查 fd 是否在 fdset 集合内,如果是则返回非 0 值,否则返回 0。

- FD_SET(fd, &fdset):将 fd 加入到 fdset 集合内。

- FD_CLR(fd, &fdset):将 fd 从 fdset 集合中移除。

例如,如果我们希望检查文件描述符 fd 是否发生读事件,就可以调用 FD_ISSET 函数,传入读事件的集合对应的 fd_set 结构体。

select函数的返回值是一个int类型的整数,其含义与返回的三个集合密切相关。

具体来说,它的取值有以下三种情况:- 如果返回值为负数,则表示 select 调用出错,具体的错误码可以通过 errno 来获取。

fd_isset函数

fd_isset函数

fd_isset函数
fd_isset函数
fd_isset函数用于检查某一文件描述符是否设置在读写集合中,fd_isset函数的返回值为非零值(即TRUE)表示设置了某一文件描述符,否则(即为FALSE)表示未设置。

fd_isset函数原型规定如下:
int fd_isset( int fd, fd_set *set );
其中,fd为要检查的描述符,set是一个文件描述符集,可以是读、写、异常三种集合中的任意一种。

fd_isset函数返回值如下:
1.当描述符存在于指定的集合中时,返回真;
2.当描述符不存在于指定的集合中时,返回假;
3.当参数错误时,或者文件描述符超出了指定集合中的最大值,则返回一个负值。

该函数使用起来很简单,但是也有一些使用上的细节,如:
1.对于每一个描述符,调用fd_isset函数之前,必须先调用
fd_set函数;
2.另外,也要考虑fd_isset函数的回调函数一定是由fd_set 函数来调用的;
3.另外,在调用fd_isset函数之前,也要确保文件描述符至少有一个空闲块,否则,它可能会返回一个负值。

总之,fd_isset函数可以用来检查文件描述符是否设置了读、
写、异常三种集合中的任意一种,并且能够返回一个正确的值,从而保证程序的正确性和安全性。

fdset参数一个用于检查可读性(readfds)[指南]

fdset参数一个用于检查可读性(readfds)[指南]

fd_set参数:一个用于检查可读性(readfds),一个用于检查可写性(writefds),另一个用于例外数据(exceptfds)。

从根本上说,fd_set数据类型代表着一系列特定套接字的集合。

其中,readfds集合包括符合下述任何一个条件的套接字:■有数据可以读入。

■连接已经关闭、重设或中止。

■假如已调用了listen,而且一个连接正在建立,那么accept函数调用会成功。

writefds集合包括符合下述任何一个条件的套接字:■有数据可以发出。

■如果已完成了对一个非锁定连接调用的处理,连接就会成功。

最后,exceptfds集合包括符合下述任何一个条件的套接字:■假如已完成了对一个非锁定连接调用的处理,连接尝试就会失败。

■有带外(Out-of-band,OOB)数据可供读取。

用select对套接字进行监视之前,在自己的应用程序中,必须将套接字句柄分配给一个集合,设置好一个或全部读、写以及例外fd_set结构。

将一个套接字分配给任何一个集合后,再来调用select,便可知道一个套接字上是否正在发生上述的I/O活动。

Winsock提供了下列宏操作,可用来针对I/O活动,对fd_set进行处理与检查:■FD_CLR(s,*set):从set中删除套接字s。

■FD_ISSET(s,*set):检查s是否set集合的一名成员;如答案是肯定的是,则返回TRUE。

■FD_SET(s,*set):将套接字s加入集合set。

■FD_ZERO(*set):将set初始化成空集合。

例如,假定我们想知道是否可从一个套接字中安全地读取数据,同时不会陷于无休止的“锁定”状态,便可使用FD_SET宏,将自己的套接字分配给fd_read集合,再来调用select。

要想检测自己的套接字是否仍属fd_read集合的一部分,可使用FD_ISSET宏。

采用下述步骤,便可完成用select操作一个或多个套接字句柄的全过程:1)使用FD_ZERO宏,初始化自己感兴趣的每一个fd_set。

select用法c语言

select用法c语言

select用法c语言在C语言中,`select`是一个系统调用,用于在多个文件描述符上监听事件。

它主要用于I/O多路复用,可以同时监听多个文件描述符的可读、可写或异常等事件。

`select`函数的定义如下:```c#include <sys/select.h>int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);```参数解释:- `nfds`:需要监视文件描述符的总数,即设置最大的文件描述符号+1,可以简单理解为fd_set中描述符的个数。

- `readfds`:需要监视可读事件的文件描述符集合。

- `writefds`:需要监视可写事件的文件描述符集合。

- `exceptfds`:需要监视异常事件的文件描述符集合。

- `timeout`:等待的时间长度。

如果为NULL,则`select`函数将会一直阻塞,直到某个文件描述符准备好或者有信号中断;如果设置为0不阻塞,立即返回。

返回值:-如果超时时间到达前,有文件描述符就绪,返回就绪文件描述符的总数。

-如果超时时间到达前没有文件描述符就绪,则返回0。

-如果出错,返回-1,并设置errno。

示例代码如下:```c#include <stdio.h>#include <sys/select.h>int main() {fd_set rfds;struct timeval tv;int retval;//监听文件描述符0 (标准输入)FD_ZERO(&rfds);FD_SET(0, &rfds);//等待5秒_sec = 5;_usec = 0;//执行selectretval = select(1, &rfds, NULL, NULL, &tv); if (retval == -1) {perror("select");} else if (retval == 0) {printf("No data within five seconds.\n");} else {if (FD_ISSET(0, &rfds)) {printf("Data is available now.\n");}}return 0;}```上述代码中,我们将标准输入(文件描述符为0)添加到`readfds`参数中,然后等待5秒钟,如果在5秒钟内有输入数据,将会输出"Data is available now.",否则输出"No data within five seconds."。

select函数用法

select函数用法

Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect、accept、recv或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回)。

可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高)方式工作的程序,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。

下面详细介绍一下!Select的函数格式(我所说的是Unix系统下的伯克利socket编程,和windows下的有区别,一会儿说明):int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);先说明两个结构体:第一,struct fd_set可以理解为一个集合,这个集合中存放的是文件描述符(filedescriptor),即文件句柄,这可以是我们所说的普通意义的文件,当然Unix下任何设备、管道、FIFO等都是文件形式,全部包括在内,所以毫无疑问一个socket就是一个文件,socket句柄就是一个文件描述符。

fd_set集合可以通过一些宏由人为来操作,比如清空集合FD_ZERO(fd_set *);将一个给定的文件描述符加入集合之中FD_SET(int ,fd_set*);将一个给定的文件描述符从集合中删除FD_CLR(int,fd_set*);检查集合中指定的文件描述符是否可以读写FD_ISSET(int ,fd_set* )。

socket通信中select函数的使用和解释

socket通信中select函数的使用和解释

socket通信中select函数的使⽤和解释select函数的作⽤:select()在SOCKET编程中还是⽐较重要的,可是对于初学SOCKET的⼈来说都不太爱⽤select()写程序,他们只是习惯写诸如conncet()、accept()、recv()或recvfrom这样的阻塞程序(所谓阻塞⽅式block,顾名思义,就是进程或是线程执⾏到这些函数时必须等待某个事件发⽣,如果事件没有发⽣,进程或线程就被阻塞,函数不能⽴即返回)。

可是使⽤select()就可以完成⾮阻塞(所谓⾮阻塞⽅式non-block,就是进程或线程执⾏此函数时不必⾮要等待事件的发⽣,⼀旦执⾏肯定返回,以返回值的不同来反映函数的执⾏情况。

如果事件发⽣则与阻塞⽅式相同,若事件没有发⽣则返回⼀个代码来告知事件未发⽣,⽽进程或线程继续执⾏,所以效率⾼)⽅式⼯作的程序,它能够监视我们需要监视的⽂件描述符的变化情况——读写或是异常。

select函数格式:select()函数的格式(所说的是Unix系统下的Berkeley Socket编程,和Windows下的有区别,⼀会⼉说明):Unix系统下解释:int select(int maxfdp, fd_set* readfds, fd_set* writefds, fd_set* errorfds, struct timeval* timeout);先说明两个结构体:第⼀:struct fd_set可以理解为⼀个集合,这个集合中存放的是⽂件描述符(file descriptor),即⽂件句柄,这可以是我们所说的普通意义的⽂件,当然Unix下任何设备、管道、FIFO等都是⽂件形式,全部包括在内,所以,毫⽆疑问,⼀个socket就是⼀个⽂件,socket句柄就是⼀个⽂件描述符。

fd_set集合可以通过⼀些宏由⼈为来操作,⽐如清空集合:FD_ZERO(fd_set*),将⼀个给定的⽂件描述符加⼊集合之中FD_SET(int, fd_set*),将⼀个给定的⽂件描述符从集合中删除FD_CLR(int, fd_set*),检查集合中指定的⽂件描述符是否可以读写FD_ISSET(int, fd_set*)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

fd_set是文件句柄的集合。

FD_ZERO 清空这个集合;
FD_SET往这个集合里面加入一个文件句柄;
FD_ISSET 查看某一个文件句柄是否被设置了;
其中,select的第二个参数是“可读”文件句柄的集合;
第三个参数是“可写”文件句柄的集合;经常使用的就是这两个参数。

你可以看一下select函数的说明,里面有的。

'fd_set') 是一组文件描述符(fd)的集合。

由于fd_set类型的长度在不同平台上不同,因此应该用一组标准的宏定义来处理此类变量:
fd_set set; FD_ZERO(&set); /* 将set清零 */ FD_SET(fd, &set); /* 将fd加入set
*/ FD_CLR(fd, &set); /* 将fd从set中清除
*/ FD_ISSET(fd, &set); /* 如果fd在set中则真
*/
在过去,一个fd_set通常只能包含少于等于32个文件描述符,因为fd_set其实只用了一个int的比特矢量来实现,在大多数情况下,检查fd_set能包括任意值的文件描述符是系统的责任,但确定你的fd_set到底能放多少有时你应该检查/修改宏FD_SETSIZE的值。

*这个值是系统相关的*,同时检查你的系统中的select() 的man手册。

有一些系统对多于1024个文件描述符的支持有问题。

#ifndef FD_SETSIZE
#define FD_SETSIZE 64
#endif /* FD_SETSIZE */
typedef struct fd_set {
u_int fd_count; /* how many are SET? */
SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */
} fd_set;
extern int PASCAL FAR __WSAFDIsSet(SOCKET, fd_set FAR *);
#define FD_CLR(fd, set) do { \
u_int __i; \
for (__i = 0; __i < ((fd_set FAR *)(set))->;fd_count ; __i++) { \
if (((fd_set FAR *)(set))->;fd_array[__i] == fd) { \
while (__i < ((fd_set FAR *)(set))->;fd_count-1) { \
((fd_set FAR *)(set))->;fd_array[__i] = \
((fd_set FAR *)(set))->;fd_array[__i+1]; \
__i++; \
} \
((fd_set FAR *)(set))->;fd_count--; \
break; \
} \
} \
} while(0)
#define FD_SET(fd, set) do { \
u_int __i; \
for (__i = 0; __i < ((fd_set FAR *)(set))->;fd_count; __i++) { \
if (((fd_set FAR *)(set))->;fd_array[__i] == (fd)) { \
break; \
} \
} \
if (__i == ((fd_set FAR *)(set))->;fd_count) { \
if (((fd_set FAR *)(set))->;fd_count < FD_SETSIZE) { \
((fd_set FAR *)(set))->;fd_array[__i] = (fd); \
((fd_set FAR *)(set))->;fd_count++; \
} \
} \
} while(0)
#define FD_ZERO(set) (((fd_set FAR *)(set))->;fd_count=0)
#define FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(fd), (fd_set FAR *)(set)) typedef int32_t __fd_mask;
#define _NFDBITS (sizeof(__fd_mask) * 8) /* 8 bits per byte */
#define __howmany(x,y) (((x)+((y)-1))/(y))
#ifndef _FD_SET
# define _FD_SET
typedef struct __fd_set {
long fds_bits[__howmany(FD_SETSIZE, (sizeof(long) * 8))];
} fd_set;
# ifndef _KERNEL
# ifdef __cplusplus
extern "C" {
# endif /* __cplusplus */
#ifdef _INCLUDE_HPUX_SOURCE
# define FD_SET(n,p) (((__fd_mask *)((p)->;fds_bits))[(n)/_NFDBITS] |= (1 << ((n) % _NFDBITS)))
# define FD_CLR(n,p) (((__fd_mask *)((p)->;fds_bits))[(n)/_NFDBITS] &= ~(1 << ((n) % _NFDBITS)))
# define FD_ISSET(n,p) (((__fd_mask *)((p)->;fds_bits))[(n)/_NFDBITS] & (1 << ((n) % _NFDBITS)))
# define FD_ZERO(p) memset((void *)(p), (int) 0, sizeof(*(p)))
#else
# define FD_SET(n,p) (__fd_set1(n, p))
# define FD_CLR(n,p) (__fd_clr(n, p))
# define FD_ISSET(n,p) (__fd_isset(n, p))
# define FD_ZERO(p) memset((void *)(p), (int) 0, sizeof(fd_set))。

相关文档
最新文档