轉載自:
http://www.chinaitpower.com/A/2005-03-03/109697.html
使用WSAAsynSelect()模型的關鍵是要搞清楚各種事件的觸發條件,不然會造成讀或寫數據混亂。
這些事件的觸發條件同樣適用于CAsyncSocket
=======================
[1]FD_READ事件觸發條件:
1.在數據到達socket后,并且從來沒有觸發過FD_READ(也就是最開始的階段)
2.在數據到達socket后,并且前一個recv()調用后
3.調用recv()后,緩沖區還有未讀完的數據
第3點過程如下:
1.100 bytes 數據到達,winsock2發出FD_READ
2.程序用recv()只讀入50 bytes,還剩下50 bytes
3.winsock2繼續發出FD_READ消息
recv()返回WSAEWOULDBLOCK的情況:
1.有數據到達,FD_READ觸發,該消息加入程序的消息隊列
2.在還沒處理該消息前,程序就把數據recv()了
3.等到處理該FD_READ消息時,程序調用recv()就會返回WSAEWOULDBLOCK(因為數據在這之前就recv()了)
注意:
1.winsock2發出一個FD_READ后,如果程序沒有用recv(),即使還有數據沒接收FD_READ也不會再觸發另一個FD_READ,要等到recv()調用后FD_READ才會發出。
2.對一個FD_READ多次recv()的情形:如果程序對一個FD_READ多次recv()將會造成觸發多個空的FD_READ,所以程序在第2次recv()前要關掉FD_READ(可以使用WSAAsynSelect關掉FD_READ),然后再多次recv()。
3.recv()返回WSAECONNABORTED,WSAECONNRESET...等消息,可以不做任何處理,可以等到FD_CLOSE事件觸發時再處理
=====================
[2]FD_ACCEPT事件觸發條件:
1.當有請求建立連接,并且從來沒有觸發過FD_ACCEPT(也就是最開始的階段)
2.當有請求建立連接,并且前一個accept()調用后
注意:當FD_ACCEPT觸發后,如果程序沒有調用accept(),即使還有建立連接的請求FD_ACCEPT也不會觸發,要直到accept()調用后
========================
[3]FD_WRITE事件觸發條件:
1.第一次connect()或accept()后(即連接建立后)
2.調用send()返回WSAEWOULDBLOCK,并且直到發送緩沖區準備好(為空)后
注意:當前一次調用send()沒有返回WSAEWOULDBLOCK時,如果緩沖區準備好了,也不會觸發FD_WRITE的
========================
[4]FD_CLOSE事件觸發條件:自己或對端中斷連接后
注意:closesocket()調用后FD_CLOSE不會觸發
========================
[5]FD_CONNECT事件觸發條件:調用了connect(),并且連接建立后。
詳細參考MSDN