linux網絡編程系列(十一)--select基本使用以及它和epoll區別

1. select函數

複用IO還有一種就是select模型,咱們下面就來簡單介紹一下select用法。socket

1.1 select函數原型

int select(int maxfdp, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
//fd_set是一個集合,裏面存放的是文件描述符,以下是一些能夠操做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中則爲真,一般用來檢查某個文件描述符是否在描述符集合中,而後去讀、寫、接收鏈接
複製代碼

struct timeval則表明超時時間,有兩個成員,一個是秒數,一個是毫秒; select參數說明:函數

  • maxfdp 表明集合中文件描述符的範圍, 即全部文件描述符的最大值加1;
  • readfds 指針指向文件描述符集合,若是描述符中有一個文件可讀, select就返回一個大於0的值(準備就緒的描述符數量), 表示有文件可讀。沒有文件可讀時則判斷是否超時, 若超時,返回0, 不然發生錯誤返回負值, 當傳入NULL時, 則表示不關心是否有文件可讀;
  • writefds 指針指向文件描述符集合,若是描述符中有一個文件可寫, select就返回一個大於0的值, 表示有文件可寫。沒有文件可寫時則判斷是否超時, 若超時,返回0, 不然發生錯誤返回負值, 當傳入NULL時, 則表示不關心是否有文件可寫;
  • errorfds 同上面兩個參數,用來監視文件錯誤異常;
  • timeout 傳入NULL時,沒有超時時間,會將select置於阻塞狀態,一直等到監視的文件描述符集合中有文件描述符發生變化爲知; 若將超時時間設爲0,則select會處於非阻塞狀態,無論文件描述符是否有變化,當即返回,文件描述符有變化時,返回大於0, 無變化時, 返回0; 超時時間大於0,則若是有文件描述符發生變化才返回,不然直到超時,才返回;

1.2 select函數調用

socket()/bind()/listen()/select()/send()/recv()/close()ui

1.3 select使用

使用select也需先將socket設置爲非阻塞的 下面演示如何使用select函數:spa

struct timeval TimeOut, *pTimeOut = NULL;
    fd_set readfds, writefds;
 FD_ZERO (&readfds);
    FD_SET (m_nSock, &readfds);
    writefds = readfds;
    TimeOut.tv_sec = 5;
    TimeOut.tv_usec=0;
 pTimeOut = &TimeOut;
 while(1)
 {
  if ((nRetVal = select (m_nSock + 1,&readfds, &writefds, NULL, pTimeOut)) == 0)
  {
   //超時
   return 0;
  }
  else if ((nRetVal < 0) && (errno == EINTR || errno == EPIPE))
   continue;
 }
複製代碼

2. 使用select如何檢測鏈接已經關閉

若是鏈接斷開了,select會返回1,但單純的select返回1並不能說明鏈接斷開了,也多是有數據可讀,因此此時須要再判斷一下read或者recv的返回值,若是返回0,就說明鏈接斷開了。 僞代碼以下:指針

fd_set read_set;
struct timeval t_o;
FD_ZERO(&read_set);
FD_SET(lSockFd,&read_set);
t_o.tv_sec = n;/* 超時秒數*/
ret = select(lSockFd + 1,&read_set,NULL,NULL,&t_o);
if(ret == 1)
{ 
 count = recv(lSockFd,buf,LEN,0);
 if((count == 0))
 {
  //說明鏈接斷開
 }
}
複製代碼

3. select和epoll的區別

  • select是輪詢fd,而epoll是先將文件描述符註冊到內核,一旦文件描述符發生變化,內核會採用回調機制激活這個文件描述符,這樣epoll_wait就會知道;
  • epoll監視的文件描述符數量沒有限制,固然跟內存也有關,而select則在內核頭文件中定義最多監視1024個文件描述符;
  • epoll效率不會隨着文件描述符數量的增加而直線降低;
  • epoll使用mmap加速內核和用戶空間的信息傳遞,避免多餘的內存拷貝;
相關文章
相關標籤/搜索