如何访问其他进程的 socket 句柄?

来源:互联网 发布:小众香水 知乎 编辑:程序博客网 时间:2024/05/27 12:22
Recv file descriptor.
代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

ssize_t recv_fd(int fd, void *ptr, size_t nbytes, int *recvfd)
{
        struct msghdr msg;
        struct iovec iov[1];
        ssize_t n;

        union {
                struct cmsghdr cm;
                char    control[CMSG_SPACE(sizeof (int))];
        } control_un;
        struct cmsghdr  *cmptr;
        msg.msg_control  = control_un.control;
        msg.msg_controllen = sizeof(control_un.control);

        msg.msg_name = NULL;
        msg.msg_namelen = 0;
        iov[0].iov_base = ptr;
        iov[0].iov_len = nbytes;
        msg.msg_iov = iov;
        msg.msg_iovlen = 1;
        if ((n = recvmsg(fd, &msg, 0)) <= 0)
                return -1;

        if ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL &&
                        cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
                if (cmptr->cmsg_level != SOL_SOCKET) 
                        return -1;
                if (cmptr->cmsg_type != SCM_RIGHTS)
                        return -1;
                *recvfd = *((int *) CMSG_DATA(cmptr));
        } else {
                *recvfd = -1;
        }
        return (n);
}

int main(int argc, char *argv[]) {
        char c;
        int fd, newfd;
        struct sockaddr_un addr;

        fd = socket(PF_UNIX, SOCK_STREAM, 0);
        bzero(&addr, sizeof(addr));
        addr.sun_family = PF_UNIX;
        strcpy(addr.sun_path, "/tmp/fd.socket");

        unlink("/tmp/fd.socket");
        bind(fd, (struct sockaddr *)&addr, sizeof(addr));

        listen(fd, 10);
        while((newfd = accept(fd, NULL, 0)) >= 0) {
                int recvfd;
                recv_fd(newfd, &c, 1, &recvfd);
                close(newfd);
                /* Now, we get the file descriptor. */
        }
}


Send file descriptor.
代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

ssize_t send_fd(int fd, void *ptr, size_t nbytes, int sendfd)
{
        struct msghdr msg;
        struct iovec iov[1];

        union {
                struct cmsghdr cm;
                char    control[CMSG_SPACE(sizeof(int))];
        } control_un;
        struct cmsghdr *cmptr;
        msg.msg_control = control_un.control;
        msg.msg_controllen = sizeof(control_un.control);
        cmptr = CMSG_FIRSTHDR(&msg);
        cmptr->cmsg_len = CMSG_LEN(sizeof(int));
        cmptr->cmsg_level = SOL_SOCKET;
        cmptr->cmsg_type = SCM_RIGHTS;
        *((int *) CMSG_DATA(cmptr)) = sendfd;

        msg.msg_name = NULL;
        msg.msg_namelen = 0;
        iov[0].iov_base = ptr;
        iov[0].iov_len = nbytes;
        msg.msg_iov = iov;
        msg.msg_iovlen = 1;
        return (sendmsg(fd, &msg, 0));
}

int main(int argc, char *argv[]) {
        int fd, sendfd;
        struct sockaddr_un addr;
        fd = socket (PF_UNIX, SOCK_STREAM, 0);
        bzero(&addr, sizeof(addr));
        addr.sun_family = PF_UNIX;
        strcpy(addr.sun_path, "/tmp/fd.socket");

        connect(fd, (struct sockaddr *)&addr, sizeof(addr));

        sendfd = open("/etc/inittab", O_RDONLY);
        /* send a file descriptor. */
        send_fd(fd, "", 1, sendfd);       
        return 0;
}