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成员进行检查)。对于错误接收,MSG_ERRQUEUEmsghdr中设置。在错误传递后,将根据下一个排队的错误重新生成挂起的套接字错误,并在下一个套接字操作上传递。

错误以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成员进行检查)。对于错误接收,MSG_ERRQUEUEmsghdr中设置。在错误传递后,将根据下一个排队的错误重新生成挂起的套接字错误,并在下一个套接字操作上传递。
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 Specification 也是如此,除了它的返回值类型为“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

广告


  

广告



广告