功能
recv 函数的功能就是从套接字中接收数据。
头文件
#include <sys/types.h>
#include <sys/socket.h>
原型
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
参数
参数 | 描述 |
---|---|
sockfd | socket 文件描述符 |
buf | 接收数据缓冲区 |
len | 接收数据缓冲区的大小 |
flags | 标志,一般置0,若需要设置多个标志,则通过 “或” 逻辑进行连接 |
flags 可以设置为如下几种:
flags 标志 |
---|
MSG_CMSG_CLOEXEC |
MSG_CMSG_CLOEXEC |
MSG_DONTWAIT |
MSG_ERRQUEUE |
MSG_OOB |
MSG_PEEK |
MSG_TRUNC |
MSG_WAITALL |
返回值
- 成功:接收到的字节数
- 失败:-1,并设置 errno
- 其他:当出现如下情况时,返回0
- 当流套接字(socket 函数中参数 type = SOCK_STREAM)对端关闭连接时,返回值将为0;
- UNIX 和 Internet 域数据报套接字允许长度为0的数据报。当接收到这样的数据报时,返回值为0;
- 当流套接字对端发送长度为0的数据段,也可以返回值0。
errno 的值可能是:
错误值 | 解释 |
---|---|
EAGAIN(11) | 套接字已标记为非阻塞,调用 recv 读取数据而此时没有数据可读,则返回该错误 |
EWOULDBLOCK | 含义同 EAGAIN,但是错误值可能不同于EAGAIN,所以这两个错误值都需要检查 |
EBADF(9) | 参数 sockfd 不是有效的描述符 |
ECONNREFUSE | 远程主机阻绝网络连接 |
EFAULT(14) | 接收缓冲区指针(参数 buf)指向进程地址空间之外 |
EINTR(4) | 操作被信号中断 |
EINVAL(22) | 参数无效 |
ENOMEM(12) | 无法为 recvmsg 函数分配内存 |
ENOTCONN | 与面向连接关联的套接字尚未被连接上(如 TCP 协议未连接,就通过调用 recv 接收数据) |
ENOTSOCK | 文件描述符 sockfd 没有引用套接字 |
特别:
- 当函数的返回值为-1,并且 (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) 的情况下,认为当前连接是正常的,可以继续接收数据。
- 在项目中,还遇到过发送端通过 close 函数关闭套接字时,没有发送长度为0的消息到接收端,接收端调用 recv 函数返回-1,errno == ENOENT。网上有解释说是:如果 socket 是被对方用 linger 为0的形式关掉,也就是直接发 RST 的方式关闭的时候,会出现这种情况。