?3. recv和W S A R e c v
對(duì)在已連接套接字上接受接入數(shù)據(jù)來(lái)說(shuō), r e c v函數(shù)是最基本的方式。它的定義如下:
int recv(
?????SOCKET s,
?????char FAR * buf,
?????int len,
?????int flags
????);
第一個(gè)參數(shù)s,是準(zhǔn)備接收數(shù)據(jù)的那個(gè)套接字。第二個(gè)參數(shù)b u f,是即將收到數(shù)據(jù)的字符緩沖,而l e n則是準(zhǔn)備接收的字節(jié)數(shù)或b u f緩沖的長(zhǎng)度。最后, f l a g s參數(shù)可以是下面的值: 0、M S G _ P E E K或M S G _ O O B。另外,還可對(duì)這些標(biāo)志中的每一個(gè)進(jìn)行按位和運(yùn)算。當(dāng)然, 0表示無(wú)特殊行為。M S G _ P E E K會(huì)使有用的數(shù)據(jù)復(fù)制到所提供的接收端緩沖內(nèi),但是沒(méi)有從系統(tǒng)緩
沖中將它刪除。另外,還返回了待發(fā)字節(jié)數(shù)。
消息取數(shù)不太好。它不僅導(dǎo)致性能下降(因?yàn)樾枰M(jìn)行兩次系統(tǒng)調(diào)用,一次是取數(shù),另一次是無(wú)M S G _ P E E K標(biāo)志的真正刪除數(shù)據(jù)的調(diào)用),在某些情況下還可能不可靠。返回的數(shù)據(jù)可能沒(méi)有反射出真正有用的數(shù)量。與此同時(shí),把數(shù)據(jù)留在系統(tǒng)緩沖,可容納接入數(shù)據(jù)的系統(tǒng)空間就會(huì)越來(lái)越少。其結(jié)果便是,系統(tǒng)減少各發(fā)送端的T C P窗口容量。由此,你的應(yīng)用就不能獲得最大的流通。最好是把所有數(shù)據(jù)都復(fù)制到自己的緩沖中,并在那里計(jì)算數(shù)據(jù)。前面曾介紹過(guò)M S G _ O O B標(biāo)志。有關(guān)詳情,參見(jiàn)前面“帶外數(shù)據(jù)”的內(nèi)容。
在面向消息或面向數(shù)據(jù)報(bào)的套接字上使用r e c v時(shí),這幾點(diǎn)應(yīng)該注意。在待發(fā)數(shù)據(jù)大于所提供的緩沖這一事件中,緩沖內(nèi)會(huì)盡量地填充數(shù)據(jù)。這時(shí), r e c v調(diào)用就會(huì)產(chǎn)生W S A E M S G S I Z E錯(cuò)誤。注意,消息長(zhǎng)錯(cuò)誤是在使用面向消息的協(xié)議時(shí)發(fā)生的。流協(xié)議把接入的數(shù)據(jù)緩存下來(lái),
并盡量地返回應(yīng)用所要求的數(shù)據(jù),即使待發(fā)數(shù)據(jù)的數(shù)量比緩沖大。因此,對(duì)流式傳輸協(xié)議來(lái)說(shuō),就不會(huì)碰到W S A E M S G S I Z E這個(gè)錯(cuò)誤。
W S A R e c v函數(shù)在r e c v的基礎(chǔ)上增加了一些新特性。比如說(shuō)重疊I / O和部分?jǐn)?shù)據(jù)報(bào)通知。
W S A R e c v的定義如下:
int WSARecv(
???????SOCKET?s,
???????LPWSABUF lpBuffers,
???????DWORD?? dwBufferCount,
???????LPWORD? lpNumberOfBytesRecved,
???????LPWSAOVERLAPPED?lpOverlapped,
???????LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE
??????);
??????
參數(shù)s,是已建立連接的套接字。第二和第三個(gè)參數(shù)是接收數(shù)據(jù)的緩沖。l p B u ff e r s參數(shù)是一個(gè)W S A B U F結(jié)構(gòu)組成的數(shù)組,而d w B u ff e r C o u n t則表明前一個(gè)數(shù)組中W S A B U F結(jié)構(gòu)的數(shù)目。
如果接收操作立即完成, l p N u m b e r O f B y t e s R e c e i v e d參數(shù)就會(huì)指向執(zhí)行這個(gè)函數(shù)調(diào)用所收到的字節(jié)數(shù)。l p F l a g s參數(shù)可以是下面任何一個(gè)值: M S G _ P E E K、M S G _ O O B、M S G _ PA RT I A L或者對(duì)這些值進(jìn)行按位和運(yùn)算之后的結(jié)果。M S G _ PA RT I A L標(biāo)志使用和出現(xiàn)的地方不同,其含
義也不同。對(duì)面向消息的協(xié)議來(lái)說(shuō),這個(gè)標(biāo)志是W S A R e c v調(diào)用返回后設(shè)置的(如果因?yàn)榫彌_空間不夠?qū)е抡麠l消息未能在這次調(diào)用中返回的話)。這時(shí),后面的W S A R e c v調(diào)用就會(huì)設(shè)置這個(gè)標(biāo)志M A S G _ PA RT I A L,直到整條消息返回,才把這個(gè)標(biāo)志清除。如果這個(gè)標(biāo)志當(dāng)作一個(gè)輸入?yún)?shù)投遞,接收操作應(yīng)該在一收到數(shù)據(jù)就結(jié)束,即使它收到的只是整條消息中的一部分。
M S G _ PA RT I A L標(biāo)志只隨面向消息的協(xié)議一起使用。每個(gè)協(xié)議的協(xié)議條目都包含一個(gè)標(biāo)志,表明是否支持這一特性。有關(guān)詳情,參見(jiàn)第5章。l p O v e r l a p p e d和l p C o m p l e t i o n R O U T I N E參數(shù)用于重疊I / O操作
4. WSARecvDisconnect
這函數(shù)與W S A S e n d D i s c o n n e c t函數(shù)對(duì)應(yīng),其定義如下:
int WSARecvDisconnect(?
????????????SOCKET s,
????????????LPWSABUF lpOUTboundDisconnectData
???????????);
和W S A S e n d D i s c o n n e c t函數(shù)的參數(shù)一樣,該函數(shù)的參數(shù)也是已建立連接的套接字句柄和
一個(gè)有效的W S A B U F結(jié)構(gòu)(帶有收到的數(shù)據(jù))。收到的數(shù)據(jù)可以只是斷開(kāi)數(shù)據(jù)。這個(gè)斷開(kāi)數(shù)據(jù)是另一端執(zhí)行W S A S e n d D i s c o n n e c t調(diào)用發(fā)出的,它不能用于接收普通數(shù)據(jù)。另外,一旦收到這個(gè)數(shù)據(jù), W S A R e c v D i s c o n n e c t函數(shù)就會(huì)取消接收遠(yuǎn)程通信方的數(shù)據(jù),其作用和調(diào)用帶有S D _ R E C V的s h u t d o w n函數(shù)相同。
5. WSARecvEx
W S A R e c v E x函數(shù)是微軟專(zhuān)有的Winsock 1擴(kuò)展,除了f l a g s參數(shù)是按值引用外,其余和r e c v函數(shù)是一樣的。它允許基層的提供者設(shè)置M S G _ PA RT I A L標(biāo)志。該函數(shù)的原型如下:
int PASCAL FAR WSARecvEx(
?????????????SOCKET s,
?????????????char FAR * buf,
?????????????int len,
?????????????int * flags
????????????);
????????????
如果收到的數(shù)據(jù)不是一條完整的消息, f l a g s參數(shù)中就會(huì)返回M S G _ PA RT I A L標(biāo)志。對(duì)面向消息的協(xié)議(即非流協(xié)議)來(lái)說(shuō),這個(gè)標(biāo)志比較有用(即非流協(xié)議)。在M S G _ PA RT I A L標(biāo)志被當(dāng)作f l a g s參數(shù)的一部分投遞,而且收到的消息又不完整時(shí),調(diào)用W S A R e c v E x,就會(huì)立即
返回收到的那個(gè)數(shù)據(jù)。如果提供的接收緩沖容納不下整條消息, W S A R e c v E x就會(huì)失敗,并出現(xiàn)W S A E M S G S I Z E 錯(cuò)誤,剩下的數(shù)據(jù)也會(huì)被截掉。注意, M S G _ PA RT I A L 標(biāo)志和W S A E M S G S I Z E錯(cuò)誤之間的確區(qū)別是:有了這個(gè)錯(cuò)誤,即使整條消息到達(dá)接收端,但由于提
供的數(shù)據(jù)緩沖太少,也不能對(duì)它進(jìn)行接收。M S G _ P E E K 和M S G _ O O B標(biāo)志還可以和W S A R e c v E x一起使用。