recv() - Unix、Linux 系统调用
Tutorials Point


  Unix 初学者指南
  Unix Shell 编程
  高级 Unix
  Unix 有用参考
  Unix 有用资源
  精选阅读

版权所有 © 2014 tutorialspoint



  主页     参考     讨论论坛     关于 TP  

recv() - Unix、Linux 系统调用


previous next AddThis Social Bookmark Button

广告

名称

recv、recvfrom、recvmsg - 从套接字接收消息

语法

#include <sys/types.h> 

#include <sys/socket.h>

ssize_t recv(int s, void *buf, size_t len, int flags);

ssize_t recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);

ssize_t recvmsg(int s, struct msghdr *msg, int flags);

描述

recvfrom() 和 recvmsg() 调用用于从套接字接收消息,无论套接字是否面向连接,都可以使用它们来接收数据。

如果 from 不为 NULL,并且底层协议提供源地址,则填充此源地址。参数 fromlen 是一个值-结果参数,初始化为与 from 关联的缓冲区的尺寸,并在返回时修改以指示存储在其中的地址的实际尺寸。

recv() 调用通常仅在 已连接 的套接字上使用(参见 connect(2)),并且与 from 参数为 NULL 的 recvfrom() 相同。

所有三个例程在成功完成时都返回消息的长度。如果消息太长而无法放入提供的缓冲区中,则可能会根据接收消息的套接字类型丢弃多余的字节。

如果套接字上没有可用的消息,则接收调用将等待消息到达,除非套接字是非阻塞的(参见 fcntl(2)),在这种情况下,将返回 -1,并且外部变量 errno 设置为 EAGAIN。接收调用通常返回任何可用的数据,最多达到请求的数量,而不是等待接收请求的全部数量。

可以使用 select(2) 或 poll(2) 调用来确定何时到达更多数据。

recv() 调用的 flags 参数是通过对以下一个或多个值进行 OR 运算形成的

标签描述
MSG_DONTWAIT
 启用非阻塞操作;如果操作将阻塞,则返回 EAGAIN(这也可以使用 O_NONBLOCKF_SETFL fcntl(2) 结合使用)。
MSG_ERRQUEUE
 此标志指定应从套接字错误队列中接收排队的错误。错误通过辅助消息传递,其类型取决于协议(对于 IPv4 IP_RECVERR)。用户应提供足够尺寸的缓冲区。有关更多信息,请参见 cmsg(3) 和 ip(7)。导致错误的原始数据包的有效负载通过 msg_iovec 作为普通数据传递。导致错误的数据报的原始目标地址通过 msg_name 提供。
对于本地错误,不传递地址(这可以使用 cmsghdrcmsg_len 成员进行检查)。对于错误接收,在 msghdr 中设置 MSG_ERRQUEUE。传递错误后,将根据下一个排队的错误重新生成挂起的套接字错误,并在下一个套接字操作上传递。

错误以 sock_extended_err 结构提供

#define SO_EE_ORIGIN_NONE 0 #define SO_EE_ORIGIN_LOCAL 1 #define SO_EE_ORIGIN_ICMP 2 #define SO_EE_ORIGIN_ICMP6 3

struct sock_extended_err { u_int32_t ee_errno; /* error number */ u_int8_t ee_origin; /* where the error originated */ u_int8_t ee_type; /* type */ u_int8_t ee_code; /* code */ u_int8_t ee_pad; u_int32_t ee_info; /* additional information */ u_int32_t ee_data; /* other data */ /* More data may follow */ };

struct sockaddr *SO_EE_OFFENDER(struct sock_extended_err *);

ee_errno 包含排队错误的 errno 编号。ee_origin 是错误源代码。其他字段是特定于协议的。宏 SOCK_EE_OFFENDER 返回指向错误源网络对象的地址的指针,该指针给定指向辅助消息的指针。如果不知道此地址,则 sockaddrsa_family 成员包含 AF_UNSPEC,并且 sockaddr 的其他字段未定义。导致错误的数据包的有效负载作为普通数据传递。
对于本地错误,不传递地址(这可以使用 cmsghdrcmsg_len 成员进行检查)。对于错误接收,在 msghdr 中设置 MSG_ERRQUEUE。传递错误后,将根据下一个排队的错误重新生成挂起的套接字错误,并在下一个套接字操作上传递。
MSG_OOB
 此标志请求接收带外数据,这些数据不会在正常数据流中接收。某些协议将快速数据放置在正常数据队列的头部,因此此标志不能与这些协议一起使用。
MSG_PEEK
 此标志导致接收操作从接收队列的开头返回数据,而不会从队列中删除该数据。因此,后续的接收调用将返回相同的数据。
MSG_TRUNC
 返回数据包的真实长度,即使它比传递的缓冲区更长。仅对数据包套接字有效。
MSG_WAITALL
 此标志请求操作阻塞,直到完全满足请求。但是,如果捕获到信号、发生错误或断开连接,或者要接收的下一个数据与返回的数据类型不同,则调用仍可能返回少于请求的数据。
recvmsg() 调用使用 msghdr 结构来最大程度地减少直接提供的参数的数量。此结构具有以下形式,如 <sys/socket.h> 中定义的那样

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 */ socklen_t msg_controllen; /* ancillary data buffer len */ int msg_flags; /* flags on received message */ };

这里 msg_namemsg_namelen 指定套接字未连接时的源地址;如果不需要或不需要名称,则 msg_name 可以指定为 null 指针。字段 msg_iovmsg_iovlen 描述分散-聚集位置,如 readv(2) 中所述。字段 msg_control(长度为 msg_controllen)指向其他协议控制相关消息或杂项辅助数据的缓冲区。当调用 recvmsg() 时,msg_controllen 应包含 msg_control 中可用缓冲区的长度;在成功调用返回后,它将包含控制消息序列的长度。
消息的形式为

struct cmsghdr { socklen_t cmsg_len; /* data byte count, including hdr */ int cmsg_level; /* originating protocol */ int cmsg_type; /* protocol-specific type */ /* followed by u_char cmsg_data[]; */ };

辅助数据只能由 cmsg(3) 中定义的宏访问。
例如,Linux 使用此辅助数据机制通过 Unix 套接字传递扩展错误、IP 选项或文件描述符。
recvmsg() 返回后,将设置 msghdr 中的 msg_flags 字段。它可以包含多个标志
MSG_EOR
 指示记录结束;返回的数据完成了一个记录(通常与类型为 SOCK_SEQPACKET 的套接字一起使用)。
MSG_TRUNC
 指示由于数据报大于提供的缓冲区而丢弃了数据报的尾部。
MSG_CTRUNC
 指示由于辅助数据缓冲区空间不足而丢弃了一些控制数据。
MSG_OOB
 返回以指示已接收加速数据或带外数据。
MSG_ERRQUEUE
 指示未接收数据,但来自套接字错误队列的扩展错误。

返回值

这些调用返回接收到的字节数,如果发生错误则返回 -1。当对等方已执行有序关闭时,返回值将为 0。

错误

这些是由套接字层生成的一些标准错误。其他错误可能会由底层协议模块生成和返回;请参阅其手册页。
标签描述
EAGAIN 套接字被标记为非阻塞,并且接收操作将阻塞,或者已设置接收超时,并且在接收数据之前超时已过期。
EBADF 参数 s 是无效的描述符。
ECONNREFUSED
 远程主机拒绝允许网络连接(通常是因为它未运行请求的服务)。
EFAULT 接收缓冲区指针指向进程地址空间之外。
EINTR 在任何数据可用之前,接收被信号传递中断。
EINVAL 传递了无效的参数。
ENOMEM 无法为 recvmsg() 分配内存。
ENOTCONN
 套接字与面向连接的协议关联,但尚未连接(参见 connect(2) 和 accept(2))。
ENOTSOCK
 参数 s 不引用套接字。

符合标准

4.4BSD(这些函数调用首次出现在 4.2BSD 中),POSIX.1-2001。

POSIX.1-2001 仅描述 MSG_OOBMSG_PEEKMSG_WAITALL 标志。

备注

上面给出的原型遵循 glibc2。Single Unix 规范与此一致,除了它具有类型为“ssize_t”的返回值(而 4.x BSD 和 libc4 和 libc5 都具有“int”)。flags 参数在 4.x BSD 中为“int”,但在 libc4 和 libc5 中为“unsigned int”。len 参数在 4.x BSD 中为“int”,但在 libc4 和 libc5 中为“size_t”。fromlen 参数在 4.x BSD、libc4 和 libc5 中为“int *”。当前的“socklen_t *”是由 POSIX 发明的。另请参见 accept(2)。

根据 POSIX.1-2001,msghdr 结构的 msg_controllen 字段应类型化为 socklen_t,但 glibc 当前(2.4)将其类型化为 size_t

另请参见



previous next Printer Friendly

广告


  

广告



广告