sendmsg recvmsg函数

sendmsg(2)与recvmsg(2)函数
这些函数为程序提供了一些其他的套接口I/O接口所不具备的高级特性。下面的内容我们将会先来看一下sendmsg来介绍这些主题。然后将会完整的介绍recvmsg函数,因为他们的函数接口是相似的。接下来,将会描述msghdr的完整结构。
sendmsg(2)函数
现在是时候进入这个大同盟了。从概念上说,sendmsg函数是所有写入函数的基础,而他是从属于套接口的。下面的列表以复杂增加的顺序列出了所有与入函数。在每一个层次上,同时列出了所增加的特性。
函数        增加的特性
write        最简单的套接口写入函数
send        增加了flags标记
sendto        增加了套接口地址与套接口长度参数
writev        没有标记与套接口地址,但是具有分散写入的能力
sendmsg        增加标记,套接口地址与长度,分散写入以及附属数据的能力
sendmsg(2)函数原型如下:
#include 
#include 
int sendmsg(int s, const struct msghdr *msg, unsigned int flags);
函数参数描述如下:
要在其上发送消息的套接口s
信息头结构指针msg,这会控制函数调用的功能
可选的标记位参数flags。这与send或是sendto函数调用的标记参数相同。
函数的返回值为实际发送的字节数。否则,返回-1表明发生了错误,而errno表明错误原因。
recvmsg(2)函数
recvmsg是与sendmsg函数相对的函数。这个函数原型如下:
#include 
#include 
int recvmsg(int s, struct msghdr *msg, unsigned int flags);
函数参数如下:
要在其上接收信息的套接口s
信息头结构指针msg,这会控制函数调用的操作。
可选标记位参数flags。这与recv或是recvfrom函数调用的标记参数相同。
这个函数的返回值为实际接收的字节数。否则,返回-1表明发生了错误,而errno表明错误原因。
理解struct msghdr
当我第一次看到他时,他看上去似乎是一个需要创建的巨大的结构。但是不要怕。其结构定义如下:
struct msghdr {
    void         *msg_name;
    socklen_t    msg_namelen;
    struct iovec *msg_iov;
    size_t       msg_iovlen;
    void         *msg_control;
    size_t       msg_controllen;
    int          msg_flags;
};
结构成员可以分为四组。他们是:
套接口地址成员msg_name与msg_namelen。
I/O向量引用msg_iov与msg_iovlen。
附属数据缓冲区成员msg_control与msg_controllen。
接收信息标记位msg_flags。
在我们将这个结构分为上面的几类以后,结构看起来就不那样巨大了。
成员msg_name与msg_namelen
这些成员只有当我们的套接口是一个数据报套接口时才需要。msg_name成员指向我们要发送或是接收信息的套接口地址。成员msg_namelen指明了这个套接口地址的长度。
当调用recvmsg时,msg_name会指向一个将要接收的地址的接收区域。当调用sendmsg时,这会指向一个数据报将要发送到的目的地址。
注意,msg_name定义为一个(void *)数据类型。我们并不需要将我们的套接口地址转换为(struct sockaddr *)。
成员msg_iov与msg_iovlen
这些成员指定了我们的I/O向量数组的位置以及他包含多少项。msg_iov成员指向一个struct iovec数组。我们将会回忆起I/O向量指向我们的缓冲区。成员msg_iov指明了在我们的I/O向量数组中有多少元素。
成员msg_control与msg_controllen
这些成员指向了我们附属数据缓冲区并且表明了缓冲区大小。msg_control指向附属数据缓冲区,而msg_controllen指明了缓冲区大小。
成员msg_flags
当使用recvmsg时,这个成员用于接收特定的标记位(他并不用于sendmsg)。在这个位置可以接收的标记位如下表所示:
标记位        描述
MSG_EOR        当接收到记录结尾时会设置这一位。这通常对于SOCK_SEQPACKET套接口类型十分有用。
MSG_TRUNC    这个标记位表明数据的结尾被截短,因为接收缓冲区太小不足以接收全部的数据。
MSG_CTRUNC    这个标记位表明某些控制数据(附属数据)被截短,因为缓冲区太小。
MSG_OOB        这个标记位表明接收了带外数据。
MSG_ERRQUEUE    这个标记位表明没有接收到数据,但是返回一个扩展错误。
我们可以在recvmsg(2)与sendmsg(2)的man手册页中查看更多的信息。
附属数据结构与宏
recvmsg与sendmsg函数允许程序发送或是接收附属数据。然而,这些额外的信息受限于一定的格式规则。这一节将会介绍控制信息头与程序将会用来管理这些信息的宏。

你可能感兴趣的:(linux)