sendmsg/recvmsg和struct msghdr

函数原型

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

两函数都用到struct msghdr:

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

msg_name  and  msg_namelen  specify the source address if the socket is unconnected; msg_name may be given as a NULL pointer if no names are desired or required.

The fields msg_iov and msg_iovlen  describe  scatter-gather  locations,  as  discussed  in  readv(2).

The field msg_control, which has length msg_controllen, points to a buffer for other protocol control-related messages or miscellaneous ancillary data.  When recvmsg()  is  called,  msg_controllen should  contain the length of the available buffer in msg_control; upon return from a successful call it will contain the length of the control message sequence.

The msg_flags field in the msghdr is set on return of recvmsg(), MSG_EOR, MSG_TRUNC, MSG_CTRUNC, MSG_OOB, MSG_ERRQUEUE.

消息的格式定义为struct cmsghdr:

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

控制消息的访问通过宏cmsg(3)实现:

       #include <sys/socket.h>

       struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *msgh);
       struct cmsghdr *CMSG_NXTHDR(struct msghdr *msgh, struct cmsghdr *cmsg);
       size_t CMSG_ALIGN(size_t length);
       size_t CMSG_SPACE(size_t length);
       size_t CMSG_LEN(size_t length);
       unsigned char *CMSG_DATA(struct cmsghdr *cmsg);

These  macros  are used to create and access control messages (also called ancillary data) that are not a part of the socket payload.

Ancillary data is a sequence of struct cmsghdr structures with appended data.  This sequence should be accessed using only the macros described in this manual page and never directly.

创建消息:

To create ancillary data, first initialize the msg_controllen member of the msghdr with the  length  of  the  control message buffer.

Use CMSG_FIRSTHDR() on the msghdr to get the first control message and CMSG_NXTHDR() to get all sub‐sequent ones.

In each control message, initialize cmsg_len (with CMSG_LEN()), the other cmsghdr header  fields,  and the  data portion using CMSG_DATA().

Finally, the msg_controllen field of the msghdr should be set to the sum of the CMSG_SPACE() of the length of all control  messages  in  the  buffer.

示例

       This code looks for the IP_TTL option in a received ancillary buffer:

           struct msghdr msgh;
           struct cmsghdr *cmsg;
           int *ttlptr;
           int received_ttl;

           /* Receive auxiliary data in msgh */
           for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
                   cmsg = CMSG_NXTHDR(&msgh,cmsg)) {
               if (cmsg->cmsg_level == IPPROTO_IP
                       && cmsg->cmsg_type == IP_TTL) {
                   ttlptr = (int *) CMSG_DATA(cmsg);
                   received_ttl = *ttlptr;
                   break;
               }
           }
           if (cmsg == NULL) {
               /*
                * Error: IP_TTL not enabled or small buffer
                * or I/O error.
                */
           }

The code below passes an array of file descriptors over a UNIX domain socket using SCM_RIGHTS:

           struct msghdr msg = {0};
           struct cmsghdr *cmsg;
           int myfds[NUM_FD]; /* Contains the file descriptors to pass. */
           char buf[CMSG_SPACE(sizeof myfds)];  /* ancillary data buffer */
           int *fdptr;

           msg.msg_control = buf;
           msg.msg_controllen = sizeof buf;
           cmsg = CMSG_FIRSTHDR(&msg);
           cmsg->cmsg_level = SOL_SOCKET;
           cmsg->cmsg_type = SCM_RIGHTS;
           cmsg->cmsg_len = CMSG_LEN(sizeof(int) * NUM_FD);
           /* Initialize the payload: */
           fdptr = (int *) CMSG_DATA(cmsg);
           memcpy(fdptr, myfds, NUM_FD * sizeof(int));
           /* Sum of the length of all control messages in the buffer: */
           msg.msg_controllen = cmsg->cmsg_len;

原文地址:https://www.cnblogs.com/embedded-linux/p/9219123.html

时间: 2024-10-09 01:29:45

sendmsg/recvmsg和struct msghdr的相关文章

struct msghdr和struct cmsghdr

struct msghdr和struct cmsghdr http://blog.csdn.net/wsllq334/article/details/6977039 structdescriptorcredentialsfilesocket数据结构 理解struct msghdr 当我第一次看到他时,他看上去似乎是一个需要创建的巨大的结构.但是不要怕.其结构定义如下: struct msghdr { void *msg_name; socklen_t msg_namelen; struct io

struct msghdr和struct cmsghdr【转载】

理解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;   

套接字I/O函数write/read writev/readv send/recv sendto/recvfrom sendmsg/recvmsg

函数原型 read/write系原型 1 #include <unistd.h> 2 3 ssize_t read(int fd, void *buf, size_t count); 1 #include <unistd.h> 2 3 ssize_t write(int fd, const void *buf, size_t count); 1 #include <sys/uio.h> 2 3 ssize_t readv(int fd, const struct iov

内核中用于数据接收的结构体struct msghdr(转)

内核中用于数据接收的结构体struct msghdr(转) 我们从一个实际的数据包发送的例子入手,来看看其发送的具体流程,以及过程中涉及到的相关数据结构.在我们的虚拟机上发送icmp回显请求包,ping另一台主机172.16.48.1.我们使用系统调用sendto发送这个icmp包. ssize_t sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);

六、高级套接字函数

网络通信的高级函数 1.recv和send 函数原型: int recv(int sockfd,void *buf,int len,int flags); int send(int sockfd,void *buf,int len,int flags); 前面的三个参数和read.write一样,第四个参数可以是0或者是以下的组合: MSG_DONTROUTE 不查找路由表 MSG_OOB 接收或者发送外带数据 MSG_PEEK 查看数据,并不从系统缓冲区移走数据 MSG_WAITALL 等待所

NetLink Communication Mechanism And Netlink Sourcecode Analysis

catalog 1. Netlink简介 2. Netlink Function API Howto 3. Generic Netlink HOWTO kernel API 4. RFC 3549 Linux Netlink as an IP Services Protocol 5. sendmsg.recvmsg In User Space 6. kernel_recvmsg.kernel_sendmsg In Kernel Space 7. NetLink Sockets C++ Libra

Linux网络编程入门 (转载)

http://www.cnblogs.com/RascallySnake/archive/2012/01/04/2312564.html (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户端        在网络程序中,如果一个程序主动和外面的程序通信,那么我们把这个程序称为客户端程序. 比如我们使用ftp程序从另外一        个地方获取文件

Linux网络编程入门

(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍 客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户端 在网络程序中,如果一个程序主动和外面的程序通信,那么我们把这个程序称为客户端程序. 比如我们使用ftp程序从另外一 个地方获取文件的时候,是我们的ftp程序主动同外面进行通信(获取文件), 所以这个地方我们的ftp程序就是客户端程序. 服务端 和客户端相对应的程序即为服务端程序.被动的等待外面的程序来和自己通

回射服务器的头文件

#ifndef _MY_ERR_H_#define _MY_ERR_H_ #include <errno.h> /* for definition of errno */#include <stdarg.h> /* ISO C variable aruments */ static void err_doit(int, int, const char *, va_list); /* * Nonfatal error related to a system call. * Print