recvmsg和sendmsg函数

参考:《UNIX 网络编程 · 卷1 : 套接字联网API》
之前的 recv 函数中介绍到,其 flags 参数在设计上存在一个基本问题:它是按值传递的,而不是一个值-结果参数。但是 recvmsg 和 sendmsg 所用的 msghdr 结构,该结构是按引用传递的,内核返回时会修改其中的 msg_flags 成员标志,如果一个进程需要内核更新标志,就需要调用 recvmsg,而不是调用 recv 或 recvfrom。

其实这两个函数也是最通用的 I/O 函数,事实上可以把所有的 read、readv、recv、recvfrom 函数调用都替换成 recvmsg 函数调用,类似各类输出函数也可替换成 sendmsg 函数。这两个函数的定义如下:

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);

返回值:成功返回读入或者写出的字节数,出错返回 -1 并设置 errno。

这两个函数的参数变少了,但是 struct msghdr 参数是个结构体,很多参数都被封装到这个结构体中了:

struct user_msghdr
{

    void *msg_name;           /* 指向地址结构 */
    int msg_namelen;          /* 地址结构长度 */
    struct iovec *msg_iov;    /* 数据 */
    int msg_iovlen;           /* 数据区个数 */
    void *msg_control;        /* 控制信息 */
    socklen_t msg_controllen; /* 控制信息缓冲区长度 */
    unsigned int msg_flags;   /* 接收信息的标志 */
};

参数说明:

msg_name 和 msg_namelen:这两个成员用于套接字未连接的场合(如 UDP 套接字)。类似于 recvfrom 和 sendto 的第五个和第六个参数:msg_name 指向一个套接字地址结构,调用者在其中存放接收者或发送者的协议地址。如果无需知名协议地址,msg_name 应为 NULL。msg_namelen 对于 sendmsg 是一个值参数,对于 recvmsg 是一个值-结果参数。

msg_iov 和 msg_iovlen:输入或者输出缓冲区数组。类似于 readv 或 writev 的第二个和第三个参数。

对于 recvmsg 和 sendmsg,我们必须区别他们两个标志变量,一个是传递的 flags 参数,另一个是传递的 msghdr 结构的 msg_flags 成员,它传递的是引用。

msg_flags :只有 recvmsg 使用 msg_flags 成员。recvmsg 被调用时,flags 参数被赋值到 msg_flags 成员,并由内核使用其值驱动接受处理过程。内核还依据 recvmsg 的结果更新 msg_flags 成员的值。而 sendmsg 则忽略 msg_flags 成员,因为它直接使用 flags 参数驱动发送处理过程。这一点意味着如果想在某个 sendmsg 调用中设置 MSG_DONTWAIT 标志,就把 flags 参数设置为该值,而msg_flags 成员设置为该值没有作用。

如下图为输入输出函数检查的 flags 参数值以及 recvmsg 可能返回的 msg_flag 成员值。其中没有 sendmsg 的 msg_flags 一栏,因为其无效。

各种 I/O 函数输入和输出标志的总结

如下示例:

图中一个 msghdr 结构体以及它指向的各种信息,假设进程即将对一个 UDP 套接字调用 recvmsg。

对一个UDP套接字调用recvmsg时的结构

接着假设从 198.6.38.100 端口 2000 到达一个 170 字节的 UDP 数据报,它的目的地是我们的 UDP 套接字,

目的 IP 地址为 206.168.112.96。其 recvmsg 返回时 msghdr 结构体中的所有信息如下:

recvmsg返回时的结构

如下图汇总了我们已讲述的五组 I/O 函数之间的差别:

五组IO函数之间的差别

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值