C函数篇(recv函数)
简述
从⼀个接收数据。
表头⽂件:
#include<sys/types.h>
#include<sys/socket.h>
int PASCAL FAR recv( s, char FAR* buf, int len, int flags);
s:⼀个标识已连接的描述字。
buf:⽤于接收数据的。
len:长度。
flags:指定调⽤⽅式。
流程
这⾥只描述同步Socket的recv函数的执⾏流程。当调⽤recv函数时:
(1)recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现⽹络错误,那么recv函数返回SOCKET_ERROR;
(2)如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字s的接收,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就⼀直等待,直到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能⼤于buf的长度,所以在这种情况下要调⽤⼏次recv函数才能把s的接收缓冲中的数据copy 完。recv函数仅仅是copy 数据,真正的接收数据是协议来完成的);
recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时⽹络中断了,那么它返回0。
注意:在Unix系统下,如果recv函数在等待协议接收数据时⽹络断开了,那么调⽤recv的进程会接收到⼀个SIGPIPE信号,进程对该信号的默认处理是进程终⽌。
实例
recv函数读数据的时候需要考虑的是当recv()返回的⼤⼩如果等于请求的⼤⼩,那么很有可能是还有数据未读完,也意味着该次事件还没有处理完,所以还需要再次读取:
1while(rs)
2 {
3 buflen = recv(activeevents[i].data.fd, buf, sizeof(buf), 0);
4if(buflen < 0)
5 {
6// 由于是⾮阻塞的模式,所以当errno为EAGAIN时,表⽰当前缓冲区已⽆数据可读
7// 在这⾥就当作是该次事件已处理
8if(errno == EAGAIN)
9break;
10else
11return;
12 }
13else if(buflen == 0)
14 {
15// 这⾥表⽰对端的socket已正常关闭.
16 }
17if(buflen != sizeof(buf))
18 rs = 0;
19else
20 rs = 1;// 需要再次读取
21 }
注释
本函数⽤于已连接的数据报或流式进⾏数据的接收。
对SOCK_STREAM类型的来说,本函数将返回所有可⽤的信息,最⼤可达的⼤⼩。如果被设置为线内接收(选项为SO_OOBINLINE),且有带外数据未读⼊,则返回带外数据。可通过调⽤的SOCATMARK命令来确定是否有待读⼊。
对于数据报类,队列中第⼀个数据报中的数据被,但最多不超过的⼤⼩。如果数据报⼤于,那么缓冲区中只有数据报的前⾯部分,其他的数据都丢失了,并且recv()函数返回WSAEMSGSIZE错误。如果没有数据待读,那么除⾮是⾮阻塞模式,不然的话将⼀直等待数据的到来,此时将返回SOCKET_ERROR错误,是WSAEWOULDBLOCK。⽤或WSAAsynSelect()可以获知何时数据到达。
如果为SOCK_STREAM类型,并且远端“优雅”地中⽌了连接,那么recv()⼀个数据也不读取,⽴即返回。如果⽴即被强制中⽌,那么recv()将以WSAECONNRESET错误失败返回。在的所设选项之上,还可⽤标志位flag来影响函数的执⾏⽅式。也就是说,本函数的语义既取决于选项,也取决于标志位参数。标志位可取下列值:
值意义
windows版本:
第四个参数:
MSG_PEEK 查看当前数据。数据将被复制到中,但并不从输⼊队列中删除。
MSG_OOB 处理(参见2.2.3节具体讨论)。
返回值:
若⽆错误发⽣,recv()返回读⼊的字节数。如果连接已中⽌,返回0。否则的话,返回SOCKET_ERROR错误,可通过WSAGetLastError()获取相应。
:
WSANOTINITIALISED:在使⽤此API之前应⾸先成功地调⽤WSAStartup()。
WSAENETDOWN:WINDOWS实现检测到⽹络⼦系统失效。
WSAENOTCONN:未连接。
WSAEINTR:阻塞进程被WSACancelBlockingCall()取消。
WSAEINPROGRESS:⼀个阻塞的WINDOWS调⽤正在运⾏中。
WSAENOTSOCK:描述字不是⼀个。
WSAEOPNOTSUPP:指定了MSG_OOB,但不是SOCK_STREAM类型的。
WSAESHUTDOWN:已被关闭。当⼀个以0或2的how参数调⽤shutdown()关闭后,⽆法再⽤recv()接收数据。WSAEWOULDBLOCK:标识为⾮阻塞模式,但接收操作会产⽣阻塞。
WSAEMSGSIZE:数据报太⼤⽆法全部装⼊,故被剪切。
WSAEINVAL:未⽤bind()进⾏捆绑。
WSAECONNABORTED:由于超时或其他原因,虚电路失效。
WSAECONNRESET:远端强制中⽌了虚电路。
linux版本:
第四个参数:
MSG_DONTROUTE 绕过路由表查。
MSG_DONTWAIT 仅本操作⾮阻塞。
MSG_OOB 发送或接收带外数据。
MSG_PEEK 窥看外来消息。
MSG_WAITALL 等待所有数据。
返回值:
若⽆错误发⽣,recv()返回读⼊的字节数。如果连接已中⽌,返回0。如果发⽣错误,返回-1,可通过perror()获取相应错误信息。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论