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;
  • 相关阅读:
    MySQL 使用 ON UPDATE CURRENT_TIMESTAMP 自动更新 timestamp (转)
    MySQL数据类型:UNSIGNED注意事项(转)
    MySQL慢查询参数
    elasticsearch中mapping的_source和store的笔记(转)
    python 使用 elasticsearch 常用方法(聚合)
    python 使用 elasticsearch 常用方法(检索)
    python 使用 elasticsearch 常用方法(索引)
    ElasticSearch集群状态查看命令大全(转)
    用C#实现修改网页数据
    基于jQuery可悬停控制图片轮播代码
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/9219123.html
Copyright © 2011-2022 走看看