C++⽹络编程之select
1、select
原型:
#include <sys/select.h>
int select(int maxfd, fd_set *rdset, fd_set *wrset, fd_set *exset, struct timeval *timeout);
功能:
select⽤来实现多路复⽤输⼊/输出模型。select系统调⽤来让我们的程序监视多个⽂件句柄的状态变化。程序会停在select处等待,知道被监视的⽂件句柄有⼀个或多个发⽣了改变,可以等待执⾏异步I/O。
参数:
maxfd是需要监视的最⼤的⽂件描述符值+1;
rdset: 指向检查可读性的套接字集合的可选的指针。
wrset: 指向检查可写性的套接字集合的可选的指针。
exset: 指向检查错误的套接字集合的可选的指针。
timeout: struct timeval结构⽤于描述⼀段时间长度,如果在这个时间内,需要监视的描述符没有事件发⽣则函数返回,返回值为0。定义如下。
#include <sys/time.h>
struct timeval
{
time_t tv_sec;//second
time_t tv_usec;//minisecond
};
若设置timeout为以下值:
NULL,则表⽰select()没有timeout,select将⼀直被阻塞,直到某个⽂件描述符上发⽣了事件。
0:仅检测描述符集合的状态,然后⽴即返回,并不等待外部事件的发⽣。
特定的时间值:如果在指定的时间段⾥没有事件发⽣,select将超时返回。
返回值:
执⾏成功则返回⽂件描述词状态已改变的个数,如果返回0代表在描述词状态改变前已超过timeout时间,没有返回;当有错误发⽣时则返回-1,错误原因存于errno,此时参数readfds,writefds,exceptfds和timeout的值变成不可预测。如果返回值为
SOCKET_ERROR,可以通过WSAGetLastError函数检索指定的错误码。
错误码解释
WSANOTINITIALISTED在使⽤此函数之前,WSAStartup函数必须成功的执⾏
WSAEFALUT 套接字执⾏时不能分配需要的资源或者readfds、writefds、exceptfds、timeval参数不是⽤户地址空间的⼀部分。
WSAENETDOWN⽹络⼦系统失败
WSAEINVAL超时值不合法的,或者其他的三个参数为空。
网络编程之delphiWSAEINTR阻塞的套接字1.1调⽤通过WSACancelBlockingCall取消WSAEINPROGRESS阻塞的套接字1.1调⽤正在处理或者服务提供者正在处理⼀个掉⽤户函数。
WSAENOTSOCK描述集中包括⼀个不是套接字的⼊⼝。
2、select模型
(1)常见的程序⽚段如下:
fs_set readset;
FD_ZERO(&readset);
FD_SET(fd,&readset);
select(fd+1,&readset,NULL,NULL,NULL);
if(FD_ISSET(fd,readset){……}
(2)理解select模型
理解select模型的关键在于理解fd_set,为说明⽅便,取fd_set长度为1字节,fd_set中的每⼀bit可以对应⼀个⽂件描述符fd。则1字节长的fd_set最⼤可以对应8个fd。
执⾏fd_set set; FD_ZERO(&set);则set⽤位表⽰是0000,0000。
若fd=5,执⾏FD_SET(fd,&set);后set变为0001,0000(第5位置为1)
若再加⼊fd=2,fd=1,则set变为0001,0011
执⾏select(6,&set,0,0,0)阻塞等待
若fd=1,fd=2上都发⽣可读事件,则select返回,此时set变为0000,0011。注意:没有事件发⽣的fd=5被清空。
基于上⾯的讨论,可以轻松得出select模型的特点:
可监控的⽂件描述符个数取决与sizeof(fd_set)的值。如果服务器上sizeof(fd_set)=512,每bit表⽰⼀个⽂件描述符,则服务器上⽀持的最⼤⽂件描述符是512*8=4096。据说可调,另有说虽然可调,但调整上限受于编译内核时的变量值。调整fd_set的⼤⼩可参
考/CppExplore/archive/2008/03/21/45061.html中的模型2(1)可以有效突破select可监控的⽂件描述符上限。
将fd加⼊select监控集的同时,还要再使⽤⼀个数据结构array保存放到select监控集中的fd,⼀是⽤于再select 返回后,array作为源数据和fd_set进⾏FD_ISSET判断。⼆是select返回后会把以前加⼊的但并⽆事件发⽣的fd清空,则每次开始 select前都要重新从array取得fd 逐⼀加⼊(FD_ZERO最先),扫描array的同时取得fd最⼤值maxfd,⽤于select的第⼀个 参数。
可见select模型必须在select前循环array(加fd,取maxfd),select返回后循环array(FD_ISSET判断是否有时间发⽣)。
3、基本原理
注:
FD_ZERO(fd_set * ):清空描述符集合
FD_SET(int , fd_set * ):向描述符添加指定描述符
FD_CLR(int, fd_set * ):从描述符集合删除指定描述符
FD_ISSET(int, fd_set * ):检测指定描述符是否在描述符集合中#define FD_SETSIZE 1024:描述符最⼤数量
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论