天天看點

Winsock2中WSAAsynSelect()模型各種事件的觸發條件

使用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