歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> socket中的select函數使用

socket中的select函數使用

日期:2017/3/1 10:10:16   编辑:Linux編程

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