選擇模型數組
fd_set結構能夠把多個套接字連在一塊兒,造成一個套接字集合服務器
typedef struct fd_set{ u_int fd_count;//下面數組的大小 SOCKET fd_array[FD_SETSIZE];//套接字句柄數組 }fd_set;
網絡事件:網絡
readfds集合:數據可讀,鏈接關閉,重啓或者中斷socket
writefds集合:數據能發送函數
exceptfds集合:OOB數據可讀spa
設置超時:code
若是爲null爲無限阻塞,知道有網絡事件發生blog
typedef struct timeval{ long tv_sec;//指示等待多少秒 long tv_usec;//指示等待多少毫秒 }timeval;
應用舉例事件
1 初始化fdSocket集合,添加監聽套接字句柄it
2 將fdSocket集合拷貝fRead傳遞給select函數,當有事件發生的時候,select函數移除fRead中沒有未決IO操做的句柄,而後返回
3 比較原來的fdSocket集合,與select處理過的fdRead集合,肯定哪些套接字有未決IO並處理這些IO
4 回到2進行選擇
1 CInitSock theSock;//初始化winsock庫 2 int main() 3 { 4 USHORT nPort=4567;//此服務器監聽的端口號 5 //建立監聽套接字 6 SOCKET sListen=::listen(AF_INET,SOCK_STREAM,IPPROTO_TCP); 7 sockaddr_in sin; 8 sin.sin_family = AF_INET; 9 sin.sin_port = htons(nPort); 10 sin.sin_addr.S_un.S_addr = INADDR_ANY; 11 //綁定套接字到本地機器 12 if(::bind(sListen,(sockaddr*)&sin,sizeof(sin))==SOCKET_ERROR) 13 { 14 printf("Failed bind()!\n"); 15 return 0; 16 } 17 //進入監聽模式 18 ::listen(sListen,5); 19 20 //select模型處理過程 21 //////////////////////////////////////////////////////////////////////////// 22 // 1 初始化fdSocket集合,添加監聽套接字句柄 23 fd_set fdSocket;//全部可用套接字集合 24 FD_ZERO(&fdSocket); 25 FD_SET(sListen,&fdSocket); 26 while(TRUE) 27 { 28 //////////////////////////////////////////////////////////////////////// 29 //2 將fdSocket集合拷貝fRead傳遞給select函數,當有事件發生的時候,select函數移除fRead中沒有未決IO操做的句柄,而後返回 30 fd_set fdRead = fdSocket; 31 int nRet = ::select(0,&fdRead,NULL,NULL,NULL); 32 if(nRet>0) 33 { 34 /////////////////////////////////////////////////////////////////// 35 // 3 比較原來的fdSocket集合,與select處理過的fdRead集合,肯定哪些套接字有未決IO並處理這些IO 36 for(int i=0;i<(int)fdSocket.fd_count;i++) 37 { 38 if(FD_ISSET(fdSocket.fd_array[i],&fdRead)) 39 { 40 if(fdSocket.fd_array[i]==sListen)// 1 監聽套接字鏈接新鏈接 41 { 42 sockaddr_in addrRemote; 43 int nAddrLen = sizeof(addrRemote); 44 SOCKET sNew = ::accept(sListen,(SOCKADDR*)&addrRemote,&nAddrLen); 45 FD_SET(sNew,&fdSocket); 46 printf("接收到鏈接(%s)\n",::inet_ntoa(addrRemote.sin_addr)); 47 } 48 else 49 { 50 printf("Too much connections!\n"); 51 continue; 52 } 53 } 54 else 55 { 56 char szText[256]; 57 int nRecv = ::recv(fdSocket.fd_array[i],szText,strlen(szText),0); 58 if(nRecv > 0)//可讀 59 { 60 szText[nRecv] = '\0'; 61 printf("接收到數據:%s\n",szText); 62 } 63 else//鏈接關閉或者重啓 64 { 65 ::closesocket(fdSocket.fd_array[i]); 66 FD_CLR(fdSocket.fd_array[i],&fdSocket); 67 } 68 } 69 } 70 } 71 else 72 { 73 printf("Failed select()!\n"); 74 break; 75 } 76 } 77 return 0; 78 }