7.recv()函数族
7.1 包含头文件
#include <sys/types.h>
#include <sys/socket.h>
7.2 函数主体
1. ssize_t recv(int sockfd, void *buf, size_t len, int flags);
2. ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
3. ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
参数解释:
- int sockfd
该参数指明从文件描述符fd的缓冲区读取数据。
- void *buf
recv()函数簇读到的数据将保存到buf所指向的空间中,用法和read()同理。
- size_t len
该参数指明本次调用接收数据的最大长度。
- int flags
如果flags设置为0,那么recv()函数和read()没有任何区别。flags还可以通过OR设置如下参数:
标志位 | 解释 |
---|---|
MSG_CMSG_CLOEXEC (仅限recvmsg()) | 此flag使用原因通open()中的O_CLOEXEC flag,再socket()中也有介绍,此处不再赘述 |
MSG_DONTWAIT | 设置本次调用为非阻塞,与O_NONBLOCK flag类似,但是该标志为作用域仅限于本次recv调用,而后者则是对文件描述符操作。 |
MSG_OOB | 此标志指定在正常数据流的接受中不会接收带外数据。某些协议将加急数据放在正常数据队列的头部,因此此标志不能与此类协议一起使用。 |
MSG_PEEK | 此标志指定从接收队列接收数据,但是不从删除队列中删除这些数据 |
MSG_TRUNC | 返回数据报(udp)的实际长度,即使它比传递的就收缓冲区更长。注意默认情况下,数据包报无法放入缓冲区时,recv调用会丢弃多余的字节 |
MSG_WAITALL | 此标志请求操作阻塞,直到满足收到的数据满足请求。 但是,如果信号被捕获、发生错误或断开连接,或者要接收的下一个数据的类型与返回的数据类型不同,则调用返回的数据可能仍少于请求的数据。 此标志对数据报套接字没有影响。 |
- *struct sockaddr src_addr
如果src_addr非NULL,且协议提供消息的源地址,则该源地址将放在 src_addr 所指向的缓冲区中。
-
*socklen_t addrlen
addrlen 是一个value-result参数。在调用之前,应将其初始化为与src_addr关联的缓冲区的大小。返回后,addrlen 将更新为包含源地址的实际大小。 如果提供的缓冲区太小,则返回的地址将被截断;在这种情况下,addrlen 将返回一个大于提供给调用的值。
如果不需要知道源地址,则可以将src_addr和addrlen均设为NULL即可。
-
struct msghdr *msg
//该结构体如下,等用到时,在进行补充
struct iovec { /* Scatter/gather array items */
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes to transfer */
};
struct msghdr {
void *msg_name; /* optional address */
socklen_t msg_namelen; /* size of address */
struct iovec *msg_iov; /* scatter/gather array */
size_t msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* ancillary data, see below */
size_t msg_controllen; /* ancillary data buffer len */
int msg_flags; /* flags on received message */
};
7.3 返回值
这些调用返回收到的字节数,如果发生错误,则返回 -1。 如果发生错误,设置了 errno 用来指示错误。当对端为流套接字且执行关闭函数时,返回值为0,表示连接正常关闭;当对端为流\域套接字时,允许收到是长度为0的数据报。错误类型如下(只列出socket层产生的错误,更底层(传输层及以下)的错误再前面文章种已经全部列出):
错误类型 | 解释 |
---|---|
EAGAIN or EWOULDBLOCK | 设置超时时间,但在改时间内没有数据到达 |
EBADF | socket并非有效的文件描述符 |
ECONNREFUSED | 对端主机拒绝了网络连接 |
EFAULT | buff缓冲区指向非法内存 |
EINTR | 在接收数据之前,本次调用被信号中断 |
EINVAL | 传递了无效参数 |
ENOTCONN | socket为面向连接套接字,但我没有成功连接 |
ENOTSOCK | socketfd用用的并不是一个socket |