1. 程式人生 > >linux下select系統呼叫

linux下select系統呼叫

struct timeval {
             long    tv_sec;         /* seconds */
             long    tv_usec;        /* microseconds */
         };
 
第2、3、4三個引數是一樣的型別: fd_set *,即我們在程式裡要申明幾個fd_set型別的變數,比如rdfds, wtfds, exfds,然後把這個變數的地址&rdfds, &wtfds, &exfds 傳遞給select函式。這三個引數都是一個控制代碼的集合,第一個rdfds是用來儲存這樣的控制代碼的:當控制代碼的狀態變成可讀的時系統就會告訴select函式返回,同理第二個wtfds是指有控制代碼狀態變成可寫的時系統就會告訴select函式返回,同理第三個引數exfds是特殊情況,即控制代碼上有特殊情況發生時系統會告訴select函式返回。特殊情況比如對方通過一個socket控制代碼發來了緊急資料。如果我們程式裡只想檢測某個socket是否有資料可讀,我們可以這樣:
fd_set rdfds; /* 先申明一個 fd_set 集合來儲存我們要檢測的 socket控制代碼 */
struct timeval tv; /* 申明一個時間變數來儲存時間 */
int ret; /* 儲存返回值 */
FD_ZERO(&rdfds); /* 用select函式之前先把集合清零 */
FD_SET(socket, &rdfds); /* 把要檢測的控制代碼socket加入到集合裡 */
tv.tv_sec = 1;
tv.tv_usec = 500; /* 設定select等待的最大時間為1秒加500毫秒 */
ret = select(socket + 1, &rdfds, NULL, NULL, &tv); /* 檢測我們上面設定到集合rdfds裡的控制代碼是否有可讀資訊 */
if(ret < 0) perror("select");/* 這說明select函數出錯 */
else if(ret == 0) printf("超時/n"); /* 說明在我們設定的時間值1秒加500毫秒的時間內,socket的狀態沒有發生變化 */
else { /* 說明等待時間還未到1秒加500毫秒,socket的狀態發生了變化 */
    printf("ret=%d/n", ret); /* ret這個返回值記錄了發生狀態變化的控制代碼的數目,由於我們只監視了socket這一個控制代碼,所以這裡一定ret=1,如果同時有多個控制代碼發生變化返回的就是控制代碼的總和了 */
    /* 這裡我們就應該從socket這個控制代碼裡讀取資料了,因為select函式已經告訴我們這個控制代碼裡有資料可讀 */
    if(FD_ISSET(socket, &rdfds)) { /* 先判斷一下socket這外被監視的控制代碼是否真的變成可讀的了 */
        /* 讀取socket控制代碼裡的資料 */
        recv(...);
    }
}
 
注意select函式的第一個引數,是所有加入集合的控制代碼值的最大那個值還要加1。比如我們建立了3個控制代碼: