标签归档:select

RSS feed of select

最后更新于 .

connect中使用了select模型,有如下地方需要注意:
我们提供的server api中有很多地方用到了select,特别是在等超时的时候,
例如:
fd_set recv_fds;
int iNum= 0;
if (m_iSocket <0) return -1;
FD_ZERO( &recv_fds );
FD_SET( m_iSocket, &recv_fds );
iNum= select( m_iSocket+1, &recv_fds, NULL, NULL, timeout );
return iNum;
这段代码对于cgi,或者简单的逻辑server不会有问题。但是对于多线程或者复杂的server可能会导致server core掉。
原因是select默认只支持1024个句柄,每个句柄采用和1024个bit对应的关系,如果fd的值超过1024,那么就会溢出。
也就是说,如果上面代码的m_iSocket>1024,那么后面的select就会溢出,即使只监听一个句柄也会溢出。奇怪的是select也不会报错。
而对于多线程或者大连接的server很有可能分配的fd超过1024.
所以建议以后写的api尽量有poll或者epoll的方式。
有poll改写了下面的代码:
int waittime = (timeout->tv_sec*1000)+(timeout->tv_usec/1000.0);
struct ...

最后更新于 .

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

(一)首先说明两个结构体:
1:struct fd_set一个存放文件描述符(file descriptor),即文件句柄的聚合,实际上是一long类型的数组,
每一个数组元素都能与一打开的文件句柄(不管是Socket句柄,还是其他文件或命名管道或设备句柄)建立联系,建立联系的工作由程序员完成;
 

FD_ZERO(fd_set *fdset):清空fdset与所有文件句柄的联系。
FD_SET(int fd, fd_set *fdset):建立文件句柄fd与fdset的联系。
FD_CLR(int fd, fd_set *fdset):清除文件句柄fd与fdset的联系。
FD_ISSET(int fd, fdset *fdset):检查fdset联系的文件句柄fd是否可读写,>0表示可读写。

2:struct timeval用来代表时间值 ...

最后更新于 .

epoll是多路复用IO(I/O Multiplexing)中的一种方式,但是仅用于linux2.6以上内核,在开始讨论这个问题之前,先来解释一下为什么需要多路复用IO. 以一个生活中的例子来解释. 假设你在大学中读书,要等待一个朋友来访,而这个朋友只知道你在A号楼,但是不知道你具体住在哪里,于是你们约好了在A号楼门口见面. 如果你使用的阻塞IO模型来处理这个问题,那么你就只能一直守候在A号楼门口等待朋友的到来,在这段时间里你不能做别的事情,不难知道,这种方式的效率是低下的. 现在时代变化了,开始使用多路复用IO模型来处理这个问题.你告诉你的朋友来了A号楼找楼管大妈,让她告诉你该怎么走.这里的楼管大妈扮演的就是多路复用IO的角色. 进一步解释select和epoll模型的差异. select版大妈做的是如下的事情:比如同学甲的朋友来了,select版大妈比较笨,她带着朋友挨个房间进行查询谁是同学甲,你等的朋友来了,于是在实际的代码中,select版大妈做的是以下的事情:

int n = select(&readset,NULL,NULL,100);
for (int i = 0; n > 0; ++i)
{
   if (FD_ISSET(fdarray[i], &readset))
   {
      do_something(fdarray ...