標籤:線程 io tcp 應用程式 socket
剛剛又看了一下I/O模型的相關知識做了一下總結,與大家一同交流.
Selct 模型說的就是在通訊端集合fd_set中的操作(可將多個通訊端連在一起,形成通訊端集合)
通訊端集合呢,又分為了3中形態,對應表示的關係如下:
通訊端集合 有事件發生 到底啥事呢
readfds select函數等待 有未決串連請求 或 資料可讀 或 串連關閉/重啟/中斷
writefds select函數等待串連成功(調用connect) 或 資料可寫
exceptfds select函數等待串連失敗 或 OOB資料可讀
而我們判斷是否可讀可寫等操作主要使用下面的方法,舉個例子:
測試某通訊端S是否可讀,將它添加到readfds中,等待select函數返回,調用完成後判讀S是否還在readfds裡面即可
大致流程就是這樣的:
(1)初始化一個通訊端集合fdsocket,添加監聽通訊端控制代碼sListen到這個集合:
fd_set fdsocket;
FD_SET(sListen,&fdSocket);
(2)當fdsockt集合的一個拷貝fdRead傳遞給select函數,當有事件發生時,select函數就會移除fdRead中沒有的未決的通訊端控制代碼,並返回:
fd_set fdRead=fdSocket;
int nRet=::select(0,&fdRead,null,null,null);
(3)通過將原來的fdSocket集合與select處理過的fdRead比較,確定有哪些通訊端有未決I/O,並進一步處理他們:
for(int i=0;i<(int)fdSocket.fd_count;i++)
{
if(FD_ISSET(fdSocket.fd_array[i],&fdRead))//判斷是否存在可讀
{
if(fdSockt.fd_array[i] == sListen)//代表監聽通訊端想連呐
{
sockaddr_in addrRemote;
int nAddrLen =sizeof(addrRemote);
SOCKET sNew=::accept(sListen,(SOCKADDR*)&addrRemote,&nAddrLen);
FD_SET(sNew,&fdSockt);
}
else//說明有資料可讀了
{
char szText[256];
int nRecv=::recv(fdSocket.fd_array[i],szText,strlen(szText),0);
}
}
}
可以知能否寫,跟這個差不多。
選擇模型的好處是能夠在單個線程內處理多個通訊端請求,但添加到fd_set結構的通訊端數量是有限的預設為64個,最多也只能到1024個。
如果通訊端過多,在調用select之前就不得不設定這1000個通訊端,select返回之後,右必須檢查這1000個通訊端。
最後是我喜歡的一句話:
某些堅持成就了一系列的偶然。
I/O模型之Select模型