《Windows網路與通訊程式設計》讀書筆試----select模型

來源:互聯網
上載者:User

select模型

具體編程流程:

1、         初始化通訊端集合fdSocket,向這個集合添加監聽通訊端。

2、         將fdSocket集合拷貝到一個每一次臨時要讀取的fdRead集合,然後將fdRead傳遞給select函數。當有事件發生
       時,select函數移除集合中沒有未決I/O操作的通訊端控制代碼,然後返回。

3、         比較原來fdSocket集合與select處理過的fdRead集合,確定哪些通訊端有未決I/O,並進一步處理這些I/O。

4、         回到第2步繼續進行處理


#define _WIN32_WINNT 0x0400   #include<windows.h>#include<cstdio>#include"InitSocket.h"CInitSock initSock ; //進入main函數前已經進行了初始化int main(void){USHORT nPort = 4567 ; //此伺服器監聽的連接埠號碼//建立監聽通訊端SOCKET sListen = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP) ;sockaddr_in sin ; sin.sin_family = AF_INET ;sin.sin_port = htons(nPort) ;sin.sin_addr.s_addr = INADDR_ANY ;//綁定通訊端到本地機器if(bind(sListen,(sockaddr* )&sin,sizeof(sin)) == SOCKET_ERROR){printf("Failed bind() \n") ;return 0 ;}//進入監聽模式listen(sListen,5) ;//select模型處理過程//初始化一個通訊端集合fdSocket,添加監聽通訊端控制代碼到這個集合fd_set fdSocket ;//所有可用通訊端集合FD_ZERO(&fdSocket) ;FD_SET(sListen,&fdSocket) ;while(TRUE){//2將fdSocket集合的一個拷貝fdRead傳遞給select函數//當有事件發生時,select函數移除fdRead集合中沒有未決I/O操作的通訊端控制代碼,然後返回。timeval reportTime ;reportTime.tv_sec = 5 ;reportTime.tv_usec = 5000 ;fd_set fdRead = fdSocket ;int nRet = select(0,&fdRead,NULL,NULL,&reportTime) ;if(nRet > 0){//確定都有哪些通訊端有未決I/O,並進一步處理這些I/O//通過將原來fdSocket集合與select處理過的fdRead集合比較for(int i = 0 ; i < (int)fdSocket.fd_count ; ++i){if(FD_ISSET(fdSocket.fd_array[i],&fdRead)){if(fdSocket.fd_array[i] == sListen)//監聽通訊端接收到新串連{if(fdSocket.fd_count < FD_SETSIZE){sockaddr_in addrRemote ;int nAddrLen = sizeof(addrRemote);SOCKET sNew = accept(sListen,(SOCKADDR *)&addrRemote,&nAddrLen) ;FD_SET(sNew,&fdSocket) ;printf("接收到串連(%s)\n",inet_ntoa(addrRemote.sin_addr)) ;}else{printf("Too much connectinos!\n") ;continue ;}}else//讀事件,結束事件也是{char szText[256] ; //int nRecv = recv(fdSocket.fd_array[i],szText,strlen(szText),0);int nRecv = recv(fdSocket.fd_array[i],szText,sizeof(szText),0);if(nRecv > 0)//可讀{szText[nRecv] = '\0' ;printf("接收到資料:%s\n",szText) ;}else//串連關閉、重啟或者中斷{printf("關閉一個串連\n") ;closesocket(fdSocket.fd_array[i]) ;FD_CLR(fdSocket.fd_array[i],&fdSocket) ;}}}}}else if(0 == nRet)//測試所用,檢測伺服器是否能夠讀出用戶端退出的訊息{printf("Time Out: %d\n",fdSocket.fd_count) ;continue ;}else{printf("Failed select() \n") ;break ;}}return 0 ;}

總結

使用select模型的好處是可以在單個線程內同時處理多個通訊端串連,這避免了阻塞模型下的線程膨脹問題。但是,添加到fd_set的結構的通訊端數量是有限制的,預設情況下,最大值FD_SETSIZE,它在winsock2.h檔案中定義為64。為了增加通訊端的數量,應用程式可以將FD_SETSIZE定義為更大值(這個定義必須在winsock2.h之前出現)。不過,自訂的值也不能超過Winsock下層提供者的限制(通常是1024)。(或者採用多個背景工作執行緒的方法,select另外64個通訊端)

另外如果FD_SETSIZE的數值過大的話,伺服器效能也會受到影響。例如,如果有1000個通訊端,那麼在調用select之前,必須設定這1000個通訊端,select返回之後,又必須檢查這1000個通訊端。


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.