关于fd_set

fd_set 函数讲解

#include<winsock.h>
函数原型:
int select(
int nfds,
fd_set* readfds,
fd_set* writefds.
fd_set* exceptfds,
const struct timeval* timeout
);

参数说明:
ndfs: 本参数忽略,仅起到兼容的作用
readfds: (可选指针)指向一组等待可读性检查的套接口
writefds: (可选指针)指向一组等待可写性检查的套接口
exceptfds:(可选指针)指向一组等待错误检查的套接口
timeout: select()最多等待时间,对堵塞操作则为NULL

函数作用说明:
本函数用于确定一个或者多个套接口的状态。对每一个套接口,调用者可查询它的可持续性、可写性以及错误状态信息。

使用fd_set结构来表示一组等待检查的套接口。在调用返回时,这个结构存有满足一定条件的套接口组的子集,并且select()返回满足一定条件的套接口的数目。

Readfds:标识等待可读性检查的套接口
如果该套接口正处于监听listen()状态,则若有连接请求到达,该套接口便被标识为可读,这样一个accept()调用保证可以无阻塞完成。

Writefds:标识等待可写性检查的套接口
如果一个套接口正在connect()连接(非阻塞),可写性意味着连接顺利建立;
如果一个套接口并未处于connect()调用中,可写性意味着send()和sendto()调用将无阻塞完成,但是并未保证在多长时间内有效,特别是多线程的环境中

Exceptfds:标识等待带外数据存在性或意味着错误条件检查的接口;

也可以将以上三个参数都设置为NULL

在winsock.h头文件中一共定义了四个宏来操作描述子集。
FD_SETSIZE变量用于确定一个集合中最多有多少个描述符
FD_SETSIZE缺省值为64,可在包含winsock.h前用#define FD_SETSIZE 来改变该值

四个宏分别是:
FD_CLR(s,*set):从集合set中删除描述符
FD_ISSET(s,*set):若s为集合中的一员,非零;否则,为零
FD_SET(s,*set):向集合添加描述字s
FD_ZERO(s,*set):将set初始化为NULL

timeout参数控制select()完成的时间.
若timeout参数为空指针,则select()将一直阻塞到有一个描述字满足条件
否则,timeout指向一个timeval结构,其中指定了select调用在返回前(返回符合条件的套接口的数目)等待多长时间

如果timeval{0,0},则select立即返回,这可用于探询所选套接口的状态。
如果处于这种状态,则select()调用可认为是非阻塞的,且一切适用于非阻塞调用的假设都适用于它。

返回值:
select()调用返回处于就绪状态并且已经包含在fd_set结构中的描述字数;

如果超时则返回0 (意思就是说 已经超过timeval设置的时间,但是还没有满足条件的描述字);
否则返回SOCKET_ERROR错误,应用程序可以通过WSAGetLastError()获取相应错误代码。

#include
#include<winsock.h>
using namespace std;

int main()
{
SOCKET sock;
sock = socket(AF_INET,SOCK_STREAM,0); //TCP协议

//结构体 告诉sock应该在什么地方监听
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htonl(1111);
addr.sin_addr.s_addr = htonl(INADDR_ANY);   //在本机上的所有ip上开始监听

bind(sock,(sockaddr*)&addr,sizeof(addr));  //绑定

listen(sock,5); //最大5个队列 

 
//用来接收一个连接
SOCKET socka;

fd_set rfd;     //描述符集 用来测试有没有一个可用的连接
FD_ZERO(&rfd);  //先清空一个描述符集

struct timeval timeout;
timeout.tv_sec = 60; 
timeout.tv_usec = 0;  

unsigned long ul = 1;
ioctlsocket(sock, FIONBIO, &ul);  //用非阻塞的连接

//使用select
/*
把sock放入要测试的描述符集就是sock放入了rfd里面,这样下一步调用select对rfd进行测试的时候就会测试sock

一个描述符集可以包含多个测试的描述符
*/
FD_SET(sock,&rfd);

if (select(sock+1,&rfd,0,0,&timeout) == 0)  //第一参数要加1
{
	// to do
}

if (FD_ISSET(sock,&rfd))  //有一个描述符满足条件  准备好了
{
	socka = accept(sock,0,0);  //一个用来读 一个用来写

	//to do

}


system("pause");
return 1;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值