📄 00000015.htm
字号:
struct msghdr msg; <BR> char buf[2]; /* send_fd()/recv_fd() 2-byte protocol */ <BR> iov[0].iov_base = buf; <BR> iov[0].iov_len = 2; <BR> msg.msg_iov = iov; <BR> msg.msg_iovlen = 1; <BR> msg.msg_name = NULL; <BR> msg.msg_namelen = 0; <BR> if (fd < 0) { <BR> msg.msg_accrights = NULL; <BR> msg.msg_accrightslen = 0; <BR> buf[1] = -fd; /* nonzero status means error */ <BR> if (buf[1] == 0) <BR> buf[1] = 1; /* -256, etc. would screw up protocol */ <BR> } else { <BR> msg.msg_accrights = (caddr_t) &fd; /* addr of descriptor */ <BR> msg.msg_accrightslen = sizeof(int); /* pass 1 descriptor */ <BR> buf[1] = 0; /* zero status means OK */ <BR> } <BR> buf[0] = 0; /* null byte flag to recv_fd() */ <BR> if (sendmsg(clifd, &msg, 0) != 2) <BR> return(-1); <BR> return(0); <BR>} <BR>程序15.7 4.3BDS下的send_fd函数 <BR>在sendnisg调用中,发送双字节协议数据(null和status字节)和描述符。 <BR>为了接收一文件描述符,我们从流管道读,直至读到null字节,它位于最后的sta <BR>tus字节之前。在此null字节之前的是一条出错消息,它来自发送者。这示于程序 <BR>15.8。 <BR>#include <sys/types.h> <BR>#include <sys/socket.h> /* struct msghdr */ <BR>#include <sys/uio.h> /* struct iovec */ <BR>#include <stddef.h> <BR>#include "ourhdr.h" <BR>/* Receive a file descriptor from another process (a server). <BR> * In addition, any data received from the server is passed <BR> * to (*userfunc)(STDERR_FILENO, buf, nbytes). We have a <BR> * 2-byte protocol for receiving the fd from send_fd(). */ <BR>int <BR>recv_fd(int servfd, ssize_t (*userfunc)(int, const void *, size_t)) <BR>{ <BR> int newfd, nread, status; <BR> char *ptr, buf[MAXLINE]; <BR> struct iovec iov[1]; <BR> struct msghdr msg; <BR> status = -1; <BR> for ( ; ; ) { <BR> iov[0].iov_base = buf; <BR> iov[0].iov_len = sizeof(buf); <BR> msg.msg_iov = iov; <BR> msg.msg_iovlen = 1; <BR> msg.msg_name = NULL; <BR> msg.msg_namelen = 0; <BR> msg.msg_accrights = (caddr_t) &newfd;/* addr of descriptor */ <BR> msg.msg_accrightslen = sizeof(int); /* receive 1 descriptor */ <BR> if ( (nread = recvmsg(servfd, &msg, 0)) < 0) <BR> err_sys("recvmsg error"); <BR> else if (nread == 0) { <BR> err_ret("connection closed by server"); <BR> return(-1); <BR> } <BR> /* See if this is the final data with null & status. <BR> Null must be next to last byte of buffer, status <BR> byte is last byte. Zero status means there must <BR> be a file descriptor to receive. */ <BR> for (ptr = buf; ptr < &buf[nread]; ) { <BR> if (*ptr++ == 0) { <BR> if (ptr != &buf[nread-1]) <BR> err_dump("message format error"); <BR> status = *ptr & 255; <BR> if (status == 0) { <BR> if (msg.msg_accrightslen != sizeof(int)) <BR> err_dump("status = 0 but no fd"); <BR> /* newfd = the new descriptor */ <BR> } else <BR> newfd = -status; <BR> nread -= 2; <BR> } <BR> } <BR> if (nread > 0) <BR> if ((*userfunc)(STDERR_FILENO, buf, nread) != nread) <BR> return(-1); <BR> if (status >= 0) /* final data has arrived */ <BR> return(newfd); /* descriptor, or -status */ <BR> } <BR>} <BR>程序15.8 4.3BSD下的recv_fd函数 <BR>注意,该程序总是准备接收一描述符(在每次调用recvmsg之前,设置msg_accrig <BR>hts和msg_accrightslen ),但是仅当在返回时msg_accrightslen非0,我们才确实 <BR>接收到一描述符。 <BR>15.3.3 4.3+BSD <BR>从4.3BSD Reno开始,更改了msghdr结构的定义。在以前版本中被称之为"存取权" <BR>的最后两个元素改称为"辅助数据"。另外,在该结构结束处增加了一个新成员msg <BR>_flags。 <BR>strcut msghdr { <BR> caddr_t msg_name; 可选的地址 <BR> int msg_namelen; 地址长度 <BR> struct iovec msg_iov; 散布/聚集数组 <BR> int msg_iovlen; 在msg_iov数组中的元素数 <BR> caddr_t msg_control; 辅助数据 <BR> int msg-controllen; 辅助数据的长度 <BR> int msg_flags; 接收到消息的标志 <BR>} <BR>现在,msg_control字段指向一个cmsghdr(控制消息头)结构。 <BR>struct cmsghdr { <BR> u_int cmsg_len; 数据的字节数,包括头 <BR> int cmsg_level; 初始的协议 <BR> int cmsg_type; 协议细节的类型 <BR> 下接真正的控制消息数据 <BR>} <BR>为了发送一文件描述符,将cmsg_len设置为cmsghdr结构长度加一个整型(描述符 <BR> <BR>)的长度。将cmsg_level设置为SOL_SOCKET,cmsg_type设置为SCM_RIGHTS,这表明 <BR>正在传送的是存取权。("SCM"表示套接口级控制消息,"socket-level control <BR>message"。)实际描述符的存放位置紧随cmsy_type字段之后,使用CMSG_DATA宏以 <BR>获得指向该整型数的指针。程序15.9示出了4.3BSD Reno之下的send_fd函数。 <BR>#include <sys/types.h> <BR>#include <sys/socket.h> /* struct msghdr */ <BR>#include <sys/uio.h> /* struct iovec */ <BR>#include <errno.h> <BR>#include <stddef.h> <BR>#include "ourhdr.h" <BR>static struct cmsghdr *cmptr = NULL; /* buffer is malloc'ed first time <BR>*/ <BR>#define CONTROLLEN (sizeof(struct cmsghdr) + sizeof(int)) <BR> /* size of control buffer to send/recv one file descriptor */ <BR>/* Pass a file descriptor to another process. <BR> * If fd<0, then -fd is sent back instead as the error status. */ <BR>int <BR>send_fd(int clifd, int fd) <BR>{ <BR> struct iovec iov[1]; <BR> struct msghdr msg; <BR> char buf[2]; /* send_fd()/recv_fd() 2-byte protocol */ <BR> iov[0].iov_base = buf; <BR> iov[0].iov_len = 2; <BR> msg.msg_iov = iov; <BR> msg.msg_iovlen = 1; <BR> msg.msg_name = NULL; <BR> msg.msg_namelen = 0; <BR> if (fd < 0) { <BR> msg.msg_control = NULL; <BR> msg.msg_controllen = 0; <BR> buf[1] = -fd; /* nonzero status means error */ <BR> if (buf[1] == 0) <BR> buf[1] = 1; /* -256, etc. would screw up protocol */ <BR> } else { <BR> if (cmptr == NULL && (cmptr = malloc(CONTROLLEN)) == NULL) <BR> return(-1); <BR> cmptr->cmsg_level = SOL_SOCKET; <BR> cmptr->cmsg_type = SCM_RIGHTS; <BR> cmptr->cmsg_len = CONTROLLEN; <BR> msg.msg_control = (caddr_t) cmptr; <BR> msg.msg_controllen = CONTROLLEN; <BR> *(int *)CMSG_DATA(cmptr) = fd; /* the fd to pass */ <BR> buf[1] = 0; /* zero status means OK */ <BR> } <BR> buf[0] = 0; /* null byte flag to recv_fd() */ <BR> if (sendmsg(clifd, &msg, 0) != 2) <BR> return(-1); <BR> return(0); <BR>} <BR>程序15.9 4.3BSD之下的send_fd函数 <BR>为了接收一描述符(程序15.10),我们为cmsghdr结构和一描述符分配足够的存储 <BR>区,设置msg_control使其指向所分配到的存储区,然后调用recvmsg。 <BR>#include <sys/types.h> <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -