zoukankan      html  css  js  c++  java
  • 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;
  • 相关阅读:
    JS LeetCode 1423. 可获得的最大点数简单题解
    SpringBoot 学集 (第六章) Docker
    Linux 学记 (第三章)
    Linux 学记 (第二章)
    Linux 学记 (第一章)
    SpringBoot 学集 (第五章) Web开发续
    SpringBoot 学集 (第四章)Web开发
    SpringBoot 学集 (第三章) 日志框架
    SpringBoot 学集 (第二章) 配置文件
    SpringBoot 学集 (第一章)
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/9219123.html
Copyright © 2011-2022 走看看