轉(zhuǎn)載自:
http://www.chinaitpower.com/A/2005-03-03/109697.html
使用WSAAsynSelect()模型的關(guān)鍵是要搞清楚各種事件的觸發(fā)條件,不然會(huì)造成讀或?qū)憯?shù)據(jù)混亂。
這些事件的觸發(fā)條件同樣適用于CAsyncSocket
=======================
[1]FD_READ事件觸發(fā)條件:
1.在數(shù)據(jù)到達(dá)socket后,并且從來(lái)沒(méi)有觸發(fā)過(guò)FD_READ(也就是最開(kāi)始的階段)
2.在數(shù)據(jù)到達(dá)socket后,并且前一個(gè)recv()調(diào)用后
3.調(diào)用recv()后,緩沖區(qū)還有未讀完的數(shù)據(jù)
第3點(diǎn)過(guò)程如下:
1.100 bytes 數(shù)據(jù)到達(dá),winsock2發(fā)出FD_READ
2.程序用recv()只讀入50 bytes,還剩下50 bytes
3.winsock2繼續(xù)發(fā)出FD_READ消息
recv()返回WSAEWOULDBLOCK的情況:
1.有數(shù)據(jù)到達(dá),F(xiàn)D_READ觸發(fā),該消息加入程序的消息隊(duì)列
2.在還沒(méi)處理該消息前,程序就把數(shù)據(jù)recv()了
3.等到處理該FD_READ消息時(shí),程序調(diào)用recv()就會(huì)返回WSAEWOULDBLOCK(因?yàn)閿?shù)據(jù)在這之前就recv()了)
注意:
1.winsock2發(fā)出一個(gè)FD_READ后,如果程序沒(méi)有用recv(),即使還有數(shù)據(jù)沒(méi)接收FD_READ也不會(huì)再觸發(fā)另一個(gè)FD_READ,要等到recv()調(diào)用后FD_READ才會(huì)發(fā)出。
2.對(duì)一個(gè)FD_READ多次recv()的情形:如果程序?qū)σ粋€(gè)FD_READ多次recv()將會(huì)造成觸發(fā)多個(gè)空的FD_READ,所以程序在第2次recv()前要關(guān)掉FD_READ(可以使用WSAAsynSelect關(guān)掉FD_READ),然后再多次recv()。
3.recv()返回WSAECONNABORTED,WSAECONNRESET...等消息,可以不做任何處理,可以等到FD_CLOSE事件觸發(fā)時(shí)再處理
=====================
[2]FD_ACCEPT事件觸發(fā)條件:
1.當(dāng)有請(qǐng)求建立連接,并且從來(lái)沒(méi)有觸發(fā)過(guò)FD_ACCEPT(也就是最開(kāi)始的階段)
2.當(dāng)有請(qǐng)求建立連接,并且前一個(gè)accept()調(diào)用后
注意:當(dāng)FD_ACCEPT觸發(fā)后,如果程序沒(méi)有調(diào)用accept(),即使還有建立連接的請(qǐng)求FD_ACCEPT也不會(huì)觸發(fā),要直到accept()調(diào)用后
========================
[3]FD_WRITE事件觸發(fā)條件:
1.第一次connect()或accept()后(即連接建立后)
2.調(diào)用send()返回WSAEWOULDBLOCK,并且直到發(fā)送緩沖區(qū)準(zhǔn)備好(為空)后
注意:當(dāng)前一次調(diào)用send()沒(méi)有返回WSAEWOULDBLOCK時(shí),如果緩沖區(qū)準(zhǔn)備好了,也不會(huì)觸發(fā)FD_WRITE的
========================
[4]FD_CLOSE事件觸發(fā)條件:自己或?qū)Χ酥袛噙B接后
注意:closesocket()調(diào)用后FD_CLOSE不會(huì)觸發(fā)
========================
[5]FD_CONNECT事件觸發(fā)條件:調(diào)用了connect(),并且連接建立后。
詳細(xì)參考MSDN