歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

socket中的select函數使用

socket select()函數用於定時檢查以創建的socket句柄的狀態,以確定設定的socket句柄當前是否可寫或有數據可讀。

select函數提供了一種方法,使得程序在操作socket時(如recv操作),無需因阻塞而等待直至超時。特別是在一個線程中操作多個socket時,對多個socket逐一操作直至超時將浪費大量時間。

select機制則是同時對多個socket句柄進行監控,一旦存在可操作的socket,函數及返回並通知程序。

select函數聲明:
int select(
 int nfds,
 fd_set* readfds,
 fd_set* writefds,
 fd_set* exceptfds,
 const struct timeval* timeout
);

fd_set是一個結構體,包含了一個SOCKET數組及一個整數用於表示數組中有效的SOCKET句柄數。

readfds參數,用於指示select函數:當其中包含的socket句柄可讀時,函數返回。
writefds和exceptfds則分別表示其中包含的socket句柄可寫或異常時,函數返回。

timeout是一個時間值結構,表示當前select函數執行時的超時時間,如果所有socket暫時都沒有可操作事件發生,則函數將一直等待直至超時,如果timeout設置為NULL時,select()函數則一直等到包含的socket存在操作事件時才返回。

select函數的返回值是一個整數。
如果執行異常,比如,指定的socket句柄是非法的等等,函數將返回SOCKET_ERROR,也就是-1.
如果select函數執行超時,即在指定的timeout時間內,沒有可操作的socket出現,那麼返回0.
其余情況函數將返回一個大於0的整數,用於指明可操作的socket總數。

由於select只返回一個表示總數的整數,那麼如果一次select多個socket句柄,或者函數執行時即指定了readfds,也指定了writefds,函數本身將無法告訴程序到底哪個socket句柄可讀或可寫。

所以在使用select時,盡量只指定檢查一個操作狀態。
不過對於同步阻塞的socket操作,writefds參數用到的機會可能會比較少。

示例:

  1. SOCKET hsock = ...  
  2.  .....  
  3.   
  4.     fd_set rds, wrs, exs;  
  5.   
  6.     FD_ZERO(&rds);     // 初始化   
  7.     FD_ZERO(&wrs);  
  8.     FD_ZERO(&exs);  
  9.   
  10.     FD_SET(hsock, &rds);    //設置socket句柄到select的FD參數中   
  11.     FD_SET(hsock, &wrs);  
  12.     FD_SET(hsock, &exs);  
  13.   
  14.     timeval timeout;  
  15.     timeout.tv_sec  = 5000;  
  16.     timeout.tv_usec = 0;  
  17.     while (int ret = select(1, NULL, &wrs, NULL, &timeout))  
  18.     {  
  19.         if ( ret == 0 ) {  
  20.             cout<<"Time Expired"<<endl;  
  21.         } else if ( ret == SOCKET_ERROR) {  
  22.             cout<<"Socket Error:"<<WSAGetLastError()<<endl;  
  23.             break;  
  24.         } else {  
  25.             cout<<"Total: "<<ret<<endl;  
  26.             break;  
  27.         }  
  28.     }  
Copyright © Linux教程網 All Rights Reserved