標籤:struct logs code use const == blog class write
1.選擇(select)模型:
選擇模型:通過一個fd_set集合管理通訊端,在滿足通訊端需求後,通知通訊端。讓通訊端進行工作。避免通訊端進入阻塞模式,進行無謂的等待。選擇模型的核心的FD_SET集合和select函數。通過該函數,我們可以們判斷通訊端上是否存在資料,或者能否向一個通訊端寫入資料。
2.select函數:
int select(
int nfds,//忽略,只是為了相容而存在。
fd_set FAR* readfds,//可讀性檢查(有資料可讀入,串連關閉,重設,終止)
fd_set FAR* writefds,//可寫性檢查(有資料可發出)
fd+set FAR* exceptfds,//帶外資料檢查(帶外資料)
const struct timeval FAR* timeout//逾時
);
3.select模型的工作步驟:
(1)首先把通訊端加入到fd_set集合
(2)檢查通訊端的可讀寫性
(3)檢查通訊端是否還在fd_set集合上
(4)處理資料
4.在三個參數中(readfds、writefds和exceptfds),任何兩個都可以是空值;但是,至少有一個不可為空值!最後一個參數timeout對應的是一個指標,它指向一個timeval結構,用於決select最多等待I/O操作完成多久的時間。如timeout是一個null 指標,那麼select函數會無限期地“等待下去,直到至少有一個通訊端符合指定的條件後返回。select成功完成後,會在fd_set集合中,返回未完成的I/O操作的通訊端控制代碼的總量。若逾時,便會返回0。不管由於什麼原因,假如select調用失敗,都會返回SOCKET_ERROR錯誤。
5.timeval結構體定義:
struct timeval
{
long tv_sec;//秒數
long tv_usec;//毫秒數
};
6.fd_set集合:用select函數對通訊端進行監視之前,必須要將通訊端分配給一個fd_set集合,設定好讀、寫以及帶外資料的fd_set結構。將一個通訊端分配給任何一個集合後,再來調用select進行監視,便可知道一個通訊端上是否正在發生上述的I/O活動。Winsock提供了下列宏操
作,對fd_set進行處理和檢查:
FD_ZERO(*set):初始化set
FD_SET(s, *set):將通訊端s加入集合set
FD_CLR(s, *set):從set中刪除通訊端s。
FD_ISSET(s,*set):檢查s是否還在集合set上,在調用select函數之前必須對此進行判斷。
7.select模型的工作步驟:
(1) 使用FD_ZERO宏,初始化自己感興趣的每一個fd_set。
(2) 使用FD_SET宏,將通訊端控制代碼分配給自己感興趣的每個fd_set。
(3) 調用select函數,等待I/O操作的完成。
(4) 根據select的傳回值,我們便可判斷出哪些通訊端存在著尚未完成(待決)的I/O操作,.具體的方法是使用FD_ISSET宏,對每個fd_set集合進行檢查。
(5) 知道了每個集合中“待決”的I/O操作之後,對I/O進行處理,然後返回步驟1 ),繼續進行select處理。
(6)select返回後,它會修改每個fd_set結構,刪除那些不存在待決I/O操作的通訊端控制代碼。這正是我們在上述的步驟( 4 )中,為何要使用FD_ISSET宏來判斷一個特定的通訊端是否仍在集合中的原因。
範例程式碼:
1 SOCKET s; 2 fd_set fdread; 3 int ret; 4 5 //初始化 6 ... 7 8 //Manage I/O on the socket 9 while(1)10 {11 FD_ZERO(&fdread);//初始化集合12 13 FD_SET(s,&fdread);//添加通訊端到集合上14 15 ret=select(0,&fdread,NULL,NULL,NULL);//調用select函數監視網路事件的完成情況16 if(ret==SOCKET_ERROR)17 {18 ...19 }20 21 if(res>0)22 {23 //處理資料24 ...25 26 if(FD_ISSET(s,&fdread))//檢查通訊端是否還在集合上27 {28 ...29 }30 }31 32 }
View Code
一.Windows I/O模型之選擇(select)模型