这两个函数是最通用的I/O函数。实际上我们可以把所有read、readv、recv和recvfrom调用替换成recvmsg调用。类似地,各种输出函数调用也可以替换成sendmsg调用。

#include <sys/socket.h>
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags);
返回:读入或写出字节数——成功;-1——出错

这两个函数把大部分参数封装到一个msghdr结构中:

struct msghdr {
void *msg_name; /* protocol address */
socklen_t msg_namelen; /* size of protocol address */
struct iovec *msg_iov; /* scatter/gather array */
int msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* ancillary data (cmsghdr struct) */
socklen_t msg_controllen; /* length of ancillary data */
int msg_flags; /* flags returned by recvmsg() */
};

这里给出的msghdr结构符合POSIX规范。有些系统仍然使用本结构源自4.2BSD的较旧版本。这个较旧的结构没有msg_flags成员,而且msg_control和msg_controllen成员分别被称为msg_accrights和msg_accrightslen。这个较旧结构唯一支持的辅助数据形式用于传递文件描述字(称为访问权限)。

msg_name和msg_namelen这两个成员用于套接口未连接的场合(譬如未连接UDP套接口)。它们类似reacvfrom和sendto的第5和第6个参数:msg_name指向一个套接口地址结构,调用者在其中存放接收者(对于sendmsg调用)或发送者(对于recvmsg调用)的协议地址。如果无需指明协议地址(例如对于TCP套接口或已连接UDP套接口),msg_name应置为空指针。msg_namelen对于sendmsg是一个值参数,对于recvmsg却是一个值-结果参数。

msg_iov和msg_iovlen这两个成员指定输入或输出缓冲区数组(即iovec结构数组),类似readv和writev的第2和第3个参数。

msg_control和msg_controllen这两个成员指定可选的辅助数据的位置和大小。

对于recvmsg和sendmsg,我们必须区别它们的两个标志变量:一个是传递值的flags参数,另一个是所传递msghdr结构的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_flags成员值。其中没有sendmsg msg_flags一栏,因为本组合无效。

标志 内核检查:

send flags

sendto flags

sendmsg flags

内核检查:

recv flags

recvfrom flags

recvmsg flags

内核返回:

recvmsg msg_flags
MSG_DONTROUTE

MSG_DONTWAIT

MSG_PEEK

MSG_WAITALL

        

        


         

         

         

 
MSG_EOR

MSG_OOB
        

        


         
             

             

MSG_BCAST

MSG_MCAST

MSG_TRUNC

MSG_CTRUNC

MSG_NOTIFICATION

                 

             

             

             

             

这些标志中,内核只检查而不返回前4个标志;既检查又返回下2个标志;不检查而只返回后5个标志。recvmsg返回的7个标志解释如下:

MSG_BCAST    本标志随BSD/OS引入,相对较新。它的返回条件是:本数据报作为链路层广播收取或者其宿IP地址是一个广播地址。

MSG_MCAST    本标志随BSD/OS引入,相对较新。它的返回条件是:本数据报作为链路层多播收取。

MSG_TRUNC    本标志的返回条件是:本数据报被截断;也就是说,内核预备返回的数据超过进程事先分配的空间(所有iov_len成员之和)。

MSG_CTRUNC  本标志的返回条件是:本数据报的辅助数据被截断;也就是说,内核预备返回的辅助数据超过进程事先分配的空间(msg_controllen)。

MSG_EOR        如果返回的数据不是一个逻辑记录的结尾所在,本标志将清零;否则本标志将设置。TCP不使用本标志,因为它是一个字节流协议。

MSG_OOB       本标志绝不为TCP带外数据返回。它用于其他协议族(例如OSI协议族)。

MSG_NOTIFICATION    本标志的返回条件是:SCTP接收端读入的本消息是一个事件通知,而不是一个数据消息。

如下图所示,展示了一个msghdr结构以及它指向的各种信息。图中假设进程即将对一个UDP套接口调用recvmsg。

图中给协议地址分配了16个字节,给辅助数据分配了20个字节。为缓冲数据初始化了3个iovec结构构成的数组:第一个指定一个100字节的缓冲区,第二个指定一个60字节的缓冲区,第三个指定一个80字节的缓冲区。我们还假设已为这个套接口设置了IP_RECVDSTADDR套接口选项,以接收所读取UDP数报的宿IP地址。

我们接着假设从192.6.38.100端口2000到达一个170字节的UDP数据报,它的目的地是我们的UDP套接口,宿IP地址为206.168.112.96。如下图所示,展示了recvmsg返回时msghdr结构中的所有信息。(图中被修改过的字段标了阴影)

如下图所示为5组I/O函数之间的差异:

UNIX网络编程读书笔记:recvmsg和sendmsg函数的更多相关文章

  1. UNIX网络编程读书笔记:地址操纵函数

    地址格式转换函数:它们在ASCII字符串(人们比较喜欢用的格式)与网络字节序的二进制值(此值存于套接口地址结构中)间转换地址. 1.inet_aton.inet_addr.inet_ntoa inet ...

  2. UNIX网络编程读书笔记:字节操纵函数

    #include <strings.h> void bzero(void *dest, size_t nbytes); void bcopy(const void *src, void * ...

  3. UNIX网络编程--读书笔记

    会集中这段时间写UNIX网络编程这本书的读书笔记,准备读三本,这一系类的文章会不断更新,一直会持续一个月多,每篇的前半部分是书中讲述的内容,每篇文章的后半部分是自己的心得体会,文章中的红色内容是很重要 ...

  4. UNIX网络编程读书笔记:简介

    认知套接口编程接口 理解原始套接口(raw socket)的概念   值得注意的是,客户和服务器是典型的用户进程,而TCP和IP协议则通常是系统内核协议栈的一部分. 上图中在TCP和UDP之间留有间隙 ...

  5. UNIX网络编程读书笔记:原始套接口

    概述 应用程序可以绕过传输层而直接使用IPv4和IPv6,这称为原始套接口(raw socket).http://www.cnblogs.com/nufangrensheng/p/3583435.ht ...

  6. UNIX网络编程读书笔记:基本SCTP套接口编程

    概述 SCTP是一个较新的传输协议,于2000年在IETF得到标准化(TCP是在1981年标准化的).它最初是为满足不断增长的IP电话市场设计的:具体地说,就是穿越因特网传输电话信令. SCTP是一个 ...

  7. Unix 网络编程 读书笔记1

    第一章: C/C++语言提供两种不同的编程模式:IPL32和PL64.► IPL32 ● 表示integer/pointer/long三种数据类型是32位(4个字节),在这种模式下,提供32位的地址空 ...

  8. UNIX网络编程读书笔记:套接口选项

    概述 有很多方法来获取和设置影响套接口的选项: getsockopt和setsockopt函数 fcntl函数 ioctl函数 getsockopt和setsockopt函数 这两个函数仅用于套接口. ...

  9. UNIX网络编程读书笔记:UNIX域协议

    概述 UNIX域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务器通信的一种方法,所用API与在不同主机上执行客户/服务器通信所用的API(套接口API)相同.UNIX域协议可视为进程间通信 ...

随机推荐

  1. HDU 5692 Snacks

    题目链接[http://acm.hdu.edu.cn/showproblem.php?pid=5692] 题意:一棵树,每个节点有权值,有两种操作:1.修改某个点的权值,2.求以x根的子树中的节点到根 ...

  2. 【BZOJ 2982】 2982: combination (卢卡斯定理)

    2982: combination Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 510  Solved: 316 Description LMZ有n个 ...

  3. 2017-2018-1 JAVA实验站 冲刺 day04

    2017-2018-1 JAVA实验站 冲刺 day04 各个成员今日完成的任务 小组成员 今日工作 完成进度 张韵琪 写博客.进行工作总结 100% 齐力锋 找背景音乐 100% 张浩林 游戏操作说 ...

  4. noip200806火柴棒等式

    试题描述: 给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A.B.C是用火柴棍拼出的整数(若该数非零,则最高位不能是0).用火柴棍拼数字0-9的拼法如图所示: 注意: 1)加号与等 ...

  5. 《python学习手册》第34章 异常对象

    基于字符串的异常 python在2.6之前可以使用字符串来定义异常,并且是通过对象标识符来匹配的(即通过is 而不是==) myexc = "My excetion string" ...

  6. li 标签中放a 标签,文字垂直居中

    <ul style="float:left"><li class="lili"> <a href="Left.aspx? ...

  7. Windows UWP开发系列 – 控件默认样式

    今天用一个Pivot控件的时候,想修改一下它的Header样式,却发现用Blend和VS无法导出它的默认样式了,导致无法下手,不知道是不是Blend的bug. 在网上搜了一下,在MSDN上还是找到了它 ...

  8. 如何删除Struts2动作的后缀扩展名

    在Struts2中,所有动作类有一个默认的后缀 .action 扩展. 例如, <struts> <package name="default" namespac ...

  9. android启动之SystemServer启动

    SystemServer是Android系统的核心,APK应用中可以直接交互的大部分系统服务都在该进程中执行,常见的比方WindowManagerServer(Wms).ActivityManager ...

  10. linux中grep命令的使用

    转载:http://blog.csdn.net/universsky/article/details/8866402 linux中grep命令的使用 grep (global search regul ...