WSAAccept()函数使用解析
首先了解accept、AcceptEx、WSAAccept的區(qū)別?.
1.?accept、WSAAccept是同步操作,AcceptEx是異步操作
2.?WSAAccept函數(shù)早accept函數(shù)基礎上添加了條件函數(shù)判斷是否接受客戶端連接
3.?AcceptEx是異步的,可以同時發(fā)出多個AcceptEx請求,支持重疊IO操作.
?WSAAccept()函數(shù):
簡述:?有條件地接受一個連接基于狀態(tài)函數(shù)的返回值,選擇創(chuàng)建或加入一個套接字組,提供QOS?flowspecs,允許連接數(shù)據(jù)的轉(zhuǎn)移。?
函數(shù)原型:
SOCKET?WSAAPI?WSAAccept?(?SOCKET?s,?struct?sockaddr?FAR?*?addr,?LPINT?addrlen,?LPCONDITIONPROC?lpfnCondition,?DWORD?dwCallbackData?);?
參數(shù)說明:?
s:標識一個套接口的描述字,該套接口在listen()后監(jiān)聽連接。?
addr:(可選)指針,指向存放通訊層所知的連接實體地址的緩沖區(qū)。addr參數(shù)的具體格式由套接口創(chuàng)建時產(chǎn)生的地址族決定。?
addrlen:(可選)指針,指向存放addr地址長度的整形數(shù)。?
lpfnCondition:(可選的)用戶提供的條件函數(shù)的進程實例地址。該函數(shù)根據(jù)參數(shù)傳入的調(diào)用者信息作出接受或拒絕的決定,并通過給結果參數(shù)賦予特定的值來(可選地)創(chuàng)建和/或加入一個套接口組。?
dwCallbackData:作為條件函數(shù)參數(shù)返回給應用程序的回調(diào)數(shù)據(jù)。WinSock不分析該參數(shù)。?返回值:?若無錯誤發(fā)生,WSAAccept()函數(shù)返回所接受套接口的描述字。否則的話,將返回INVALID_SOCKET錯誤,應用程序可通過WSAGetLastError()來獲取相應的錯誤代碼。?addrlen參數(shù)引用的整形數(shù)初始時包含了addr參數(shù)所指向的空間數(shù),在調(diào)用返回時包含了返回地址的實際長度。
?
附錄
這個WSAAccept函數(shù)提取第一個連接在隊列中等待將要連接的socket,并檢查它的條件函數(shù),提供了指定條件函數(shù)(即非NULL)。如果條件函數(shù)返回CF_ACCEPT,WSAAccept創(chuàng)建一個新的套接字和執(zhí)行任何套接字分組所顯示的結果參數(shù)g在條件函數(shù)中。新創(chuàng)建的套接字具有socket相同的屬性包括異步事件注冊WSAAsyncSelect或WSAEventSelect,但不包括監(jiān)聽套接字的組ID。如果條件函數(shù)返回CF_REJECT,WSAAccept拒絕連接請求。條件函數(shù)運行在相同的線程作為該函數(shù)的功能,應盡快返回。條件函數(shù)應該返回?CF_DEFER表明沒有作出決定,沒有行動關于這個服務提供者連接請求。當應用程序準備采取行動在連接請求時,它將并返回再次調(diào)用WSAAccept?CF_ACCEPT?或者?CF_REJECT作為條件函數(shù)的返回值。?一個套接字在默認模式(阻塞)會阻塞,直到連接存在,當一個應用程序調(diào)用WSAAccept和沒有連接上pendng隊列?一個套接字的非阻塞模式(阻塞)失敗與錯誤WSAEWOULDBLOCK當一個應用程序調(diào)用WSAAccept和沒有連接上pendng隊列。WSAAccept后成功,并返回一個新的套接字處理,接受插座不能用于接受任何更多的連接。原始套接字保持開放和監(jiān)聽新的連接請求。?參數(shù)是一個結果的addr的參數(shù)填寫的地址連接實體,作為已知的通信層。的確切格式addr參數(shù)是由家庭地址的通信發(fā)生。這個addrlen是一個值的結果參數(shù);它應該最初包含空格的數(shù)量由addr指出。在返回時,它將包含實際的長度(字節(jié))的地址返回。這個調(diào)用是使用面向連接的套接字類型如襪子流。如果addr和/或addrlen等于零,那么任何關于遠程地址返回接受套接字。否則,這兩個參數(shù)將被填滿,不管條件函數(shù)指定或返回內(nèi)容。?
一個條件函數(shù)的原型如下:?
int?CALLBACK?ConditionFunc(?IN?LPWSABUF?lpCallerId,?IN?LPWSABUF?lpCallerData,?IN?OUT?LPQOS?lpSQOS,?IN?OUT?LPQOSlpGQOS,?IN?LPWSABUF?lpCalleeId,?OUT?LPWSABUF?lpCalleeData,?OUT?GROUP?FAR?*?g,?IN?DWORD?dwCallbackData);?
?
ConditionFunc是應用程序提供的回調(diào)函數(shù)的占位符。函數(shù)必須位于一個DLL或應用程序模塊的實際情況。它是在模塊定義文件中導出。?
UseMakeProcInstance一個過程實例的回調(diào)函數(shù)的地址。
lpCallerId參數(shù)是一個值,該值的參數(shù),該參數(shù)包含連接實體的地址。的lpCallerData是一個數(shù)值參數(shù),包含任何用戶數(shù)據(jù)。這些參數(shù)中的信息一起被發(fā)送的連接請求。如果無來電顯示識別主叫方數(shù)據(jù)是可用的,相應的參數(shù)為NULL。許多網(wǎng)絡協(xié)議不支持連接時的主叫方數(shù)據(jù)。大多數(shù)傳統(tǒng)的網(wǎng)絡協(xié)議可以預計到支持主叫方ID信息,在連接請求的時間。?lpCallerId點的buf所指向的WSABUF部分一個SOCKADDR。根據(jù)它的地址族(通常由鑄造的的SOCKADDR一些類型特定的地址族)的的SOCKADDR的解釋。
lpSQOS參數(shù)的引用FLOWSPEC的結構為插座指定的來電,為每個方向之一,任何額外的供應商特定的參數(shù)。適用于任何單向插座的發(fā)送或接收流規(guī)范值將被忽略。一個NULL值表明,有沒有調(diào)用者提供QOS和,沒有談判是可能的。一個非NULL?lpSQOS的指針指示的QoS協(xié)商是發(fā)生或供應商沒有談判,準備接受QOS要求。 lpGQOS參數(shù)(保留以供將來使用插座組)引用的FLOWSPEC的結構套接字組的調(diào)用者創(chuàng)建,為每個方向之一,任何額外的供應商特定的參數(shù)。?lpGQOS一個NULL值表示無來電顯示提供的服務質(zhì)量。如果協(xié)商是發(fā)生的服務質(zhì)量信息可以被返回。
lpCalleeId是一個值參數(shù),包含本地地址,所連接的實體。?lpCalleeId點的buf所指向的WSABUF部分一個SOCKADDR。根據(jù)它的地址族(通常由鑄造的的SOCKADDR一些類型特定的地址族)的的SOCKADDR被解釋。
lpCalleeData是一個結果參數(shù),用于為所使用的條件的函數(shù)來提供用戶數(shù)據(jù)返回到連接的實體。最初的lpCalleeData->?len個包含由服務提供商分配的緩沖區(qū),并指出,通過lpCalleeData?-?>緩沖區(qū)的長度。通過用戶數(shù)據(jù)返回給調(diào)用者的值為零,則表示不支持。條件函數(shù)復制到lpCalleeData->?len個字節(jié)的數(shù)據(jù)到lpCalleeData?-?>緩沖區(qū),然后更新lpCalleeData->?len個顯示實際傳輸?shù)淖止?jié)數(shù)。如果沒有用戶數(shù)據(jù)將被傳遞回給調(diào)用者,條件函數(shù)應設置lpCalleeData的?-?>?len個零。所有的地址和用戶數(shù)據(jù)的格式的特定套接字所屬的地址族。 保留供未來使用插座組:分配的結果參數(shù)g在條件函數(shù)來表示以下操作: 1、若果&g是一個現(xiàn)有的插座組ID,加s到該組,本組所設定的所有要求得到滿足;2、如果&g?=?SG_UNCONSTRAINED_GROUP的,創(chuàng)建一個無約束的插座組,有S的第一個成員;3、如果&g?=?SG_CONSTRAINED_GROUP的,創(chuàng)建一個受限的插座組,有S的第一個成員;4、如果&g?=零,沒有組進行操作。 對于無約束的群體,任何一組插槽可以組合在一起,只要他們支持由一個單一的服務提供商。可以由一個有限的插座組僅面向連接的套接字,并要求所有組合插座上的連接到相同的地址在同一主機上。對于新創(chuàng)建的套接字組,新的組ID可以檢索利用getsockopt選項SO_GROUP_ID,如果此操作成功完成。一個插座組及其相關聯(lián)的ID仍然有效,直到最后一個套接字被關閉屬于該插座組。插座組ID是唯一的,對于一個給定的服務供應商的所有進程。 dwCallbackData參數(shù)值傳遞的條件功能的dwCallbackData在原來的WSAAccept調(diào)用的參數(shù)傳遞的值。這個值被解釋只能由Windows套接字第2版客戶端。這允許客戶端通過一些WSAAccept調(diào)用網(wǎng)站的條件函數(shù)的上下文信息。這也提供了與任何所需的附加信息,以確定是否接受的連接或沒有的功能的條件。一個典型的用法是通過適當投指針的數(shù)據(jù)結構,它包含與此套接字關聯(lián)的應用程序定義的對象的引用。
錯誤代碼
WSANOTINITIALISED?在調(diào)用本API之前應成功調(diào)用WSAStartup()。?WSAECONNREFUSED?根據(jù)條件函數(shù)的返回值(CF_REJECT)強制拒絕連接請求。?WSAENETDOWN?網(wǎng)絡子系統(tǒng)失效。?
WSAEFAULT?addrlen參數(shù)太小(小于sockaddr結構的大小),或者lpfnCondition并不是用戶空間的一部分。?
WSAEINTR?通過WSACancelBlockingCall()函數(shù)取消(阻塞)調(diào)用。?
WSAEINPROGRESS?一個阻塞WinSock調(diào)用正在進行。?
WSAEINVAL?WSAAccept()調(diào)用前未執(zhí)行listen()調(diào)用;條件函數(shù)中的g參數(shù)非法;條件函數(shù)的返回值非法;套接口處于非法狀態(tài)。?
WSAEMFILE?WSAAccept()調(diào)用時排隊隊列非空,且無可用套接口描述字。?WSAENOBUFS?無可用緩沖區(qū)空間。?
WSAENOTSOCK?描述字不是一個套接口。?
WSAEOPNOTSUPP?所引用的套接口不是支持面向連接服務類型的。?WSATRY_AGAIN?根據(jù)條件函數(shù)的返回值(CF_DEFER)?,連接請求被推遲。?
WSAEWOULDBLOCK?套接口標志為非阻塞,無連接請求供接受。?
WSAEACCES?被推遲的連接請求超時或撤銷。?另請參閱:accept(),?bind(),?connect(),?getsockopt(),listen(),?select(),?socket(),?SAAsyncSelect(),?WSAConnect().
總結
以上是生活随笔為你收集整理的WSAAccept()函数使用解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WinSock三种选择I/O模型
- 下一篇: TCP打洞技术