事件對象:
??????事件對象也屬于內(nèi)核對象,包含一個計數(shù)器,一個用于指明該事件是一個自動重置的事件還是一個人工重置的事件的布爾值,另一個用于指明該事件是處于已通知還是未通知狀態(tài)的布爾值。
兩種事件對象:
1.人工重置的事件。?? 當(dāng)一個人工重置的事件得到通知時,等待該事件的所有線程均為可調(diào)度線程。
2.自動重置的事件。?? 當(dāng)一個自動重置的事件得到通知時,等待該事件的線程中只有一個線程變?yōu)榭烧{(diào)動線程。
關(guān)鍵代碼段:
關(guān)鍵代碼段(臨界區(qū))工作在用戶方式下。
關(guān)鍵代碼段(臨界區(qū))是指一小代碼段,在代碼能夠執(zhí)行前,它必須獨占對某些資源的訪問權(quán)。
線程死鎖:
線程1擁有了臨界區(qū)對象A,等待臨界區(qū)對象B的擁有權(quán),線程2擁有了臨界區(qū)對象B,等待臨界區(qū)對象A的擁有權(quán),就造成了死鎖。
互斥對象、事件對象和關(guān)鍵代碼段的比較
互斥對象和事件對象都屬于內(nèi)核對象,利用內(nèi)核對象進行線程同步,速度較慢,但利用互斥對象和事件對象這樣的內(nèi)核對象,可以在多個進程中的各個線程間進行同步。
關(guān)鍵代碼段是工作在用戶方式下,同步速度較快,但在使用關(guān)鍵代碼段時,很容易進入死鎖狀態(tài),因為在等待進入關(guān)鍵代碼段時無法設(shè)定超時值。
推薦書目:《Windows核心編程》機械工業(yè)出版社
基于消息的異步套接字
Windows套接字在2種模式下執(zhí)行I/O操作,阻塞和非阻塞。
在阻塞模式下,在I/O操作完成前,執(zhí)行操作的Winsock函數(shù)會一直等待下去,不會立即返回程序(將控制權(quán)交還給程序)。
在非阻塞模式下,Winsock函數(shù)無論如何都會立即返回。
?Windows? Sockets為了支持Windows消息驅(qū)動機制,使應(yīng)用程序開發(fā)者能方便的處理網(wǎng)絡(luò)通信,它對網(wǎng)絡(luò)事件采取了基于消息的異步存取策略。
Windows Sockets的異步選擇函數(shù)WSAAsyncSelect()提供了消息機制的網(wǎng)絡(luò)事件選擇,當(dāng)使用它登記的網(wǎng)絡(luò)事件發(fā)生時,Windows應(yīng)用程序相應(yīng)窗口函數(shù)將收到一個消息,消息中指示了發(fā)生的網(wǎng)絡(luò)事件,以及與事件相關(guān)的一些信息。
相關(guān)函數(shù)說明
int? WSAEnumProtocols(LPINT?? lpiProtocols, LPWSAPROTOCOL_INFO? lpProtocolBuffer,? ILPDWORD? lpdwBufferLength);
Win32平臺支持多種不同的網(wǎng)絡(luò)協(xié)議,采用Winsock2,? 就可直接使用任何一種協(xié)議的網(wǎng)絡(luò)應(yīng)用程序了。通過WSAEnumrotocols函數(shù)可以獲得系統(tǒng)中安裝的網(wǎng)絡(luò)協(xié)議的信息。
lpPrototocols:一個以NULL結(jié)尾的協(xié)議標(biāo)示號數(shù)組,這個參數(shù)是可選的,如果lpProtocol為NULL,則返回所有可用協(xié)議的信息,否則,只返回數(shù)組中協(xié)議的信息。
lpProtocolBuffer? [out],一個用WSAPROTOCOL_INFO結(jié)構(gòu)體填充的緩沖區(qū)。WSAPROTOCOL_INFO用來存放或者得到一個指定協(xié)議的完整信息。
lpdwBufferLength [in , out],在輸入時,指定傳遞給WSAEnumProtocols()函數(shù)的lpProtocolBuffer緩沖區(qū)的長度;
在輸出時,存有獲取所有請求信息需傳遞給WSAEnumrotocols()函數(shù)的最小緩沖區(qū)長度。
這個函數(shù)不能重復(fù)調(diào)用,傳入的緩沖區(qū)必須足夠大以便能存放所有的元素。
這個規(guī)定降低了該函數(shù)的復(fù)雜度,并且由于一個機器上裝載的協(xié)議數(shù)目往往是很少的,所以不會產(chǎn)生問題。
SOCKET?? WSASocket(int?? af,???int?? type,? int?? protocol?? ,LPWSAPROTOCOL_INFO?? lpProtpcolInfo,?? GROUP??? g,? DWORD??? dwFliags);
前3個參數(shù)和socket()函數(shù)的前3個參數(shù)含義一樣。
lpProtocolInfo,一個指向WSAPROTOCOL_INFO結(jié)構(gòu)體的指針,該結(jié)構(gòu)定義了所創(chuàng)建的套接字的特性。如果lpProtocolInfo為NULL,則套接字綁定到與指定的結(jié)構(gòu)WSAPROTOCOL_INFO相關(guān)的提供者。
?g?? ,保留的。
dwFlags, 套接字屬性的描述。
int????WSARecvFrom(SOCKET???s, LPWSABUF??? lpBuffer,? DWORD? dwBufferCount? , LPDWORD?? lpNumberOfBytesRecvd,?? LPDWORD?? lpFlags,? struct? sockaddr *? lpFrom,? LPINT? lpFromLen,?? LPWSAOVERLAPPED?? lpOverLapped,? LPWSAOVERLAPPED_COMPLETION_ROUTINE??? lpCompletionRountine)
s,標(biāo)示套接字的描述符。
lpBuffer[in, out]? ,一個指向WSABUF結(jié)構(gòu)體的指針。每一個WSABUF結(jié)構(gòu)體包含一個緩沖區(qū)的指針和緩沖區(qū)的長度。
dwBufferCount,? lpBuffer數(shù)組中WSABUF結(jié)構(gòu)體的數(shù)目。
lpNumberOfBytesRecvd??? [out],? 如果接收操作立即完成,則為一個指向本次調(diào)用所接收的字節(jié)數(shù)的指針。
lpFlags[in ,out] ,一個指向標(biāo)示位的指針。
lpFrom[out], 可選指針,指向重疊操作完成后存放源地址的緩沖區(qū)。
lpFrpmLen[in,? out],指向緩沖區(qū)大小的指針,僅當(dāng)指定了lpFrom才需要。
lpOverlapped,一個指向WSAOVERLAPPED結(jié)構(gòu)體的指針(對于非重疊套接字則忽略)。
lpCompletionRoutine,? 一個指向接收操作完成時調(diào)用的完成例程的指針(對于非重疊套接字則忽略)。
int? WSASendTo(SOCKET? s,? LPWSABUF? lpBuffer,? DWORD? dwufferCount, LPDWORD?? lpNumberOfBytesSent,? DWORD? dwFlags, const struct sockaddr FAR *?? lpTo, int?? iToLen,? LPWSAOVERLAPPED?? lpOverLapped,? LPOVERLAPPED_COMPLETION_ROUTINE? lpCompletionRoutine)
s, 標(biāo)示一個套接字(可能已連接)的描述符。
lpBuffer,? 一個指向WSABUF結(jié)構(gòu)體的指針。每一個WSABUF的結(jié)構(gòu)體包含一個緩沖區(qū)的指針和緩沖區(qū)的長度。
dwBufferCount,? lpBuffer數(shù)組中WSABUF的數(shù)目。
lpNumberOfBytesSent? [out],? 如果發(fā)送操作立即完成,則為一個本次調(diào)用的所發(fā)送的字節(jié)數(shù)的指針。
dwFlags,? 指示影響操作行為的標(biāo)示位。
lpTo,? 可選指針,指向目標(biāo)套接字的地址。
iToLen,? lpTo的地址長度。
lpOverLapped,? 一個指向WSAOVERLAPPED結(jié)構(gòu)的指針(對于非重疊套接字則忽略)。
lpComletionRoutine, 一個指向操作完成時調(diào)用的完成例程的指針(對于非重疊套接字則忽略)。