2013.3.23-2

这是一篇好的文章,给与我的工作很大的帮助。

从4.3BSDReno开始,更改了msghdr结构的定义。在以前版本中被称之为存取权的最后两个元素改称为辅助数据。另外,在该结构结束处增加了一个新成员msg_flags。

strcut msghdr {
caddr_t msg_name; 可选的地址
int msg_namelen; 地址长度
struct iovec msg_iov; 散布/聚集数组
int msg_iovlen; 在msg_iov数组中的元素数
caddr_t msg_control; 辅助数据
int msg-controllen; 辅助数据的长度
int msg_flags; 接收到消息的标志
}

现在,msg_control字段指向一个cmsghdr(控制消息头)结构。

struct cmsghdr {
u_int cmsg_len; 数据的字节数,包括头
int cmsg_level; 初始的协议
int cmsg_type; 协议细节的类型下接真正的控制消息数据

}

  为了发送一文件描述符,将cmsg_len设置为cmsghdr结构长度加一个整型(描述符 )的长度。将cmsg_level设置为SOL_SOCKET,cmsg_type设置为SCM_RIGHTS,这表明正在传送的是存取权。(SCM表示套接口级控制消息,socket-level controlmessage。)实际描述符的存放位置紧随cmsy_type字段之后,使用CMSG_DATA宏以获得指向该整型数的指针。程序15.9示出了4.3BSD Reno之下的send_fd函数。

#include 
#include /* struct msghdr */
#include /* struct iovec */
#include 
#include 
#include ourhdr.h
static struct cmsghdr *cmptr = NULL; /* buffer is malloced first time */
#define CONTROLLEN (sizeof(struct cmsghdr) + sizeof(int))
/* size of control buffer to send/recv one file descriptor */
/* Pass a file descriptor to another process.
* If fd0, then -fd is sent back instead as the error status. */
int
send_fd(int clifd, int fd)
{
struct iovec iov[1];
struct msghdr msg;
char buf[2]; /* send_fd()/recv_fd() 2-byte protocol */
iov[0].iov_base = buf;
iov[0].iov_len = 2;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
if (fd 0) {
msg.msg_control = NULL;
msg.msg_controllen = 0;
buf[1] = -fd; /* nonzero status means error */
if (buf[1] == 0)
buf[1] = 1; /* -256, etc. would screw up protocol */
} else {
if (cmptr == NULL (cmptr = malloc(CONTROLLEN)) == NULL)
return(-1);
cmptr-cmsg_level = SOL_SOCKET;
cmptr-cmsg_type = SCM_RIGHTS;
cmptr-cmsg_len = CONTROLLEN;
msg.msg_control = (caddr_t) cmptr;
msg.msg_controllen = CONTROLLEN;
*(int *)CMSG_DATA(cmptr) = fd; /* the fd to pass */
buf[1] = 0; /* zero status means OK */
}
buf[0] = 0; /* null byte flag to recv_fd() */
if (sendmsg(clifd, msg, 0) != 2)
return(-1);
return(0);
}

  程序15.9 4.3BSD之下的send_fd函数

  为了接收一描述符(程序15.10),我们为cmsghdr结构和一描述符分配足够的存储区,设置msg_control使其指向所分配到的存储区,然后调用recvmsg。

#include 
#include /* struct msghdr */
#include /* struct iovec */
#include 
#include ourhdr.h
static struct cmsghdr *cmptr = NULL; /* malloced first time */
#define CONTROLLEN (sizeof(struct cmsghdr) + sizeof(int))
/* size of control buffer to send/recv one file descriptor */
/* Receive a file descriptor from another process (a server).
* In addition, any data received from the server is passed
* to (*userfunc)(STDERR_FILENO, buf, nbytes). We have a
* 2-byte protocol for receiving the fd from send_fd(). */
int
recv_fd(int servfd, ssize_t (*userfunc)(int, const void *, size_t))
{
int newfd, nread, status;
char *ptr, buf[MAXLINE];
struct iovec iov[1];
struct msghdr msg;
status = -1;
for ( ; ; ) {
iov[0].iov_base = buf;
iov[0].iov_len = sizeof(buf);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
if (cmptr == NULL (cmptr = malloc(CONTROLLEN)) == NULL)
return(-1);
msg.msg_control = (caddr_t) cmptr;
msg.msg_controllen = CONTROLLEN;
if ( (nread = recvmsg(servfd, msg, 0)) 0)err_sys(recvmsg error);
else if (nread == 0) {err_ret(connection closed by server);
return(-1);
}
/* See if this is the final data with null status.
Null must be next to last byte of buffer, status
byte is last byte. Zero status means there must
be a file descriptor to receive. */
for (ptr = buf; ptr buf[nread]; ) {
if (*ptr++ == 0) {
if (ptr != buf[nread-1])err_dump(message format error);
status = *ptr 255;
if (status == 0) {
if (msg.msg_controllen != CONTROLLEN)err_dump(status = 0 but no fd);
newfd = *(int *)CMSG_DATA(cmptr); /* new descriptor */
} else
newfd = -status;
nread -= 2;
}
}
if (nread 0)
if ((*userfunc)(STDERR_FILENO, buf, nread) != nread)
return(-1);
if (status = 0) /* final data has arrived */
return(newfd); /* descriptor, or -status */
}
}

  程序15.10 4.3BSD之下的recv_fd函数

 文章出处:http://www.yesky.com/392/81392.shtml

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值