3. recv和W S A R e c v
对在已连接套接字上接受接入数据来说, r e c v函数是最基本的方式。它的定义如下:
int recv(
SOCKET s,
char FAR * buf,
int len,
int flags
);
第一个参数s,是准备接收数据的那个套接字。第二个参数b u f,是即将收到数据的字符缓冲,而l e n则是准备接收的字节数或b u f缓冲的长度。最后, f l a g s参数可以是下面的值: 0、M S G _ P E E K或M S G _ O O B。另外,还可对这些标志中的每一个进行按位和运算。当然, 0表示无特殊行为。M S G _ P E E K会使有用的数据复制到所提供的接收端缓冲内,但是没有从系统缓
冲中将它删除。另外,还返回了待发字节数。
消息取数不太好。它不仅导致性能下降(因为需要进行两次系统调用,一次是取数,另一次是无M S G _ P E E K标志的真正删除数据的调用),在某些情况下还可能不可靠。返回的数据可能没有反射出真正有用的数量。与此同时,把数据留在系统缓冲,可容纳接入数据的系统空间就会越来越少。其结果便是,系统减少各发送端的T C P窗口容量。由此,你的应用就不能获得最大的流通。最好是把所有数据都复制到自己的缓冲中,并在那里计算数据。前面曾介绍过M S G _ O O B标志。有关详情,参见前面“带外数据”的内容。
在面向消息或面向数据报的套接字上使用r e c v时,这几点应该注意。在待发数据大于所提供的缓冲这一事件中,缓冲内会尽量地填充数据。这时, r e c v调用就会产生W S A E M S G S I Z E错误。注意,消息长错误是在使用面向消息的协议时发生的。流协议把接入的数据缓存下来,
并尽量地返回应用所要求的数据,即使待发数据的数量比缓冲大。因此,对流式传输协议来说,就不会碰到W S A E M S G S I Z E这个错误。
W S A R e c v函数在r e c v的基础上增加了一些新特性。比如说重叠I / O和部分数据报通知。
W S A R e c v的定义如下:
int WSARecv(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPWORD lpNumberOfBytesRecved,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE
);
参数s,是已建立连接的套接字。第二和第三个参数是接收数据的缓冲。l p B u ff e r s参数是一个W S A B U F结构组成的数组,而d w B u ff e r C o u n t则表明前一个数组中W S A B U F结构的数目。
如果接收操作立即完成, l p N u m b e r O f B y t e s R e c e i v e d参数就会指向执行这个函数调用所收到的字节数。l p F l a g s参数可以是下面任何一个值: M S G _ P E E K、M S G _ O O B、M S G _ PA RT I A L或者对这些值进行按位和运算之后的结果。M S G _ PA RT I A L标志使用和出现的地方不同,其含
义也不同。对面向消息的协议来说,这个标志是W S A R e c v调用返回后设置的(如果因为缓冲空间不够导致整条消息未能在这次调用中返回的话)。这时,后面的W S A R e c v调用就会设置这个标志M A S G _ PA RT I A L,直到整条消息返回,才把这个标志清除。如果这个标志当作一个输入参数投递,接收操作应该在一收到数据就结束,即使它收到的只是整条消息中的一部分。
M S G _ PA RT I A L标志只随面向消息的协议一起使用。每个协议的协议条目都包含一个标志,表明是否支持这一特性。有关详情,参见第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参数用于重叠I / O操作
4. WSARecvDisconnect
这函数与W S A S e n d D i s c o n n e c t函数对应,其定义如下:
int WSARecvDisconnect(
SOCKET s,
LPWSABUF lpOUTboundDisconnectData
);
和W S A S e n d D i s c o n n e c t函数的参数一样,该函数的参数也是已建立连接的套接字句柄和
一个有效的W S A B U F结构(带有收到的数据)。收到的数据可以只是断开数据。这个断开数据是另一端执行W S A S e n d D i s c o n n e c t调用发出的,它不能用于接收普通数据。另外,一旦收到这个数据, W S A R e c v D i s c o n n e c t函数就会取消接收远程通信方的数据,其作用和调用带有S D _ R E C V的s h u t d o w n函数相同。
5. WSARecvEx
W S A R e c v E x函数是微软专有的Winsock 1扩展,除了f l a g s参数是按值引用外,其余和r e c v函数是一样的。它允许基层的提供者设置M S G _ PA RT I A L标志。该函数的原型如下:
int PASCAL FAR WSARecvEx(
SOCKET s,
char FAR * buf,
int len,
int * flags
);
如果收到的数据不是一条完整的消息, f l a g s参数中就会返回M S G _ PA RT I A L标志。对面向消息的协议(即非流协议)来说,这个标志比较有用(即非流协议)。在M S G _ PA RT I A L标志被当作f l a g s参数的一部分投递,而且收到的消息又不完整时,调用W S A R e c v E x,就会立即
返回收到的那个数据。如果提供的接收缓冲容纳不下整条消息, W S A R e c v E x就会失败,并出现W S A E M S G S I Z E 错误,剩下的数据也会被截掉。注意, M S G _ PA RT I A L 标志和W S A E M S G S I Z E错误之间的确区别是:有了这个错误,即使整条消息到达接收端,但由于提
供的数据缓冲太少,也不能对它进行接收。M S G _ P E E K 和M S G _ O O B标志还可以和W S A R e c v E x一起使用。