網絡編程之select


一、select函數簡介

  select一般用在socket網絡編程中,在網絡編程的過程中,經常會遇到許多阻塞的函數,網絡編程時使用的recv, recvfrom、connect函數都是阻塞的函數,當函數不能成功執行的時候,程序就會一直阻塞在這里,無法執行下面的代碼。這是就需要用到非阻塞的編程方式,使用 selcet函數就可以實現非阻塞編程。
selcet函數是一個輪循函數,即當循環詢問文件節點,可設置超時時間,超時時間到了就跳過代碼繼續往下執行

  select(),確定一個或多個套接口的狀態,本函數用於確定一個或多個套接口的狀態,對每一個套接口,調用者可查詢它的可讀性、可寫性及錯誤狀態信息,用fd_set結構來表示一組等待檢查的套接口,在調用返回時,這個結構存有滿足一定條件的套接口組的子集,並且select()返回滿足條件的套接口的數目。

  通常采用select實現多路復用,也就是說可以同時監聽多個文件描述符;

下面是select的函數原型:

1   /* According to POSIX.1-2001 */
2  #include <sys/select.h>
3  
4  int select(int nfds, fd_set *readfds, fd_set *writefds,
5                fd_set *exceptfds, struct timeval *timeout);

下面進行具體的解釋:

第一個參數:int nfds--->是一個整數值,是指集合中所有文件描述符的范圍,即所有文件描述符的最大值加1

第二個參數:fd_set *readfds---->用來檢查一組可讀性的文件描述符

第三個參數:fd_set *writefds---->用來檢查一組可寫性的文件描述符

第四個參數:fd_set *exceptfds---->用來檢查文件文件描述符是否異常

第五個參數:sreuct timeval *timeout--->是一個時間結構體,用來設置超時時間

timeout:最多等待時間,對阻塞操作則為NULL

select函數的返回值
負值:select錯誤
正值:表示某些文件可讀或可寫
0:等待超時,沒有可讀寫或錯誤的文件

下面是一些跟select一起使用的函數及結構的作用

1 void FD_ZERO(fd_set *set);//清空一個文件描述符的集合
2 void FD_SET(int fd, fd_set *set);//將一個文件描述符添加到一個指定的文件描述符集合中
3 void FD_CLR(int fd, fd_set *set);//將一個指定的文件描述符從集合中清除;
4 int  FD_ISSET(int fd, fd_set *set);//檢查集合中指定的文件描述符是否可以讀寫

 

struct timeval結構是用來設置超時時間的,該結構體可以精確到秒跟毫秒

1  struct timeval {
2         time_t         tv_sec;     /* seconds */
3          suseconds_t    tv_usec;    /* microseconds */
4 };

下面是select常用的一個例子:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, cahr **argv)
 {
    struct timeval timeout;
    int ret = 0;
    fd_set rfds;
 
    FD_ZERO(&rfds);//清空描述符集合 
    FD_SET(0, &rfds);//將標准輸入(stdin)添加到集合中
    FD_SET(sockfd, &rfds);//將我們的套接字描述符添加到集合中
    /*設置超時時間*/
    timeout.tv_sec = 1;   
    timeout.tv_usec = 0;

    /*監聽套接字是否為可讀*/
    ret = select(sockfd+1, &rfds, NULL, NULL, &timeout);
    if(ret == -1) {//select 連接失敗
        perror("select failure\n");
        return 1;
    }   
    else if(ret == 0) {//超時(timeout)
        return 1;
    }   

    if(FD_ISSET(pesockfd, &rfds)) {//如果可讀
                    
            //recv or recvfrom
            ..................
    }
    
   return 0; 
  }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM