如何使用 sendmsg() 在 2 个进程之间通过套接字发送文件描述符? [英] How to use sendmsg() to send a file-descriptor via sockets between 2 processes?

查看:13
本文介绍了如何使用 sendmsg() 在 2 个进程之间通过套接字发送文件描述符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

@cnicutar 在这个问题上回答我之后 问题,我试图将文件描述符从父进程发送给它的子进程.基于此示例,我写了这段代码:

After @cnicutar answers me on this question, I tried to send a file-descriptor from the parent process to its child. Based on this example, I wrote this code:

int socket_fd ,accepted_socket_fd, on = 1;
int server_sd, worker_sd, pair_sd[2];
struct sockaddr_in client_address;
struct sockaddr_in server_address;

/* =======================================================================
 * Setup the network socket.
 * =======================================================================
 */

if((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
    perror("socket()");
    exit(EXIT_FAILURE);
}

if((setsockopt(socket_fd, SOL_SOCKET,  SO_REUSEADDR, (char *) &on, sizeof(on))) < 0)
{
    perror("setsockopt()");
    exit(EXIT_FAILURE);
}

server_address.sin_family = AF_INET;                 /* Internet address type */
server_address.sin_addr.s_addr = htonl(INADDR_ANY);  /* Set for any local IP */
server_address.sin_port = htons(port);               /* Set to the specified port */

if(bind(socket_fd, (struct sockaddr *) &server_address, sizeof(server_address)) < 0)
{
    perror("bind()");
    exit(EXIT_FAILURE);
}

if(listen(socket_fd, buffers) < 0)
{
    perror("listen()");
    exit(EXIT_FAILURE);
}

if(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair_sd) < 0)
{
    socketpair("bind()");
    exit(EXIT_FAILURE);
}

server_sd = pair_sd[0];
worker_sd = pair_sd[1];



/* =======================================================================
 * Worker processes
 * =======================================================================
 */    

struct iovec   iov[1];
struct msghdr  child_msg;
char   msg_buffer[80];
int pass_sd, rc;


/* Here the parent process create a pool of worker processes (its children) */
for(i = 0; i < processes; i++)
{
    if(fork() == 0)
    {
        // ...

        /* Loop forever, serving the incoming request */
        for(;;)
        {

            memset(&child_msg,   0, sizeof(child_msg));
            memset(iov,    0, sizeof(iov));

            iov[0].iov_base = msg_buffer;
            iov[0].iov_len  = sizeof(msg_buffer);
            child_msg.msg_iov     = iov;
            child_msg.msg_iovlen  = 1;
            child_msg.msg_name    = (char *) &pass_sd;
            child_msg.msg_namelen = sizeof(pass_sd);

            printf("Waiting on recvmsg
");
            rc = recvmsg(worker_sd, &child_msg, 0);
            if (rc < 0)
            {
               perror("recvmsg() failed");
               close(worker_sd);
               exit(-1);
            }
            else if (child_msg.msg_namelen <= 0)
            {
               printf("Descriptor was not received
");
               close(worker_sd);
               exit(-1);
            }
            else
            {
               printf("Received descriptor = %d
", pass_sd);
            }

            //.. Here the child process can handle the passed file descriptor
        }
    }

}



/* =======================================================================
 * The parent process
 * =======================================================================
 */

struct msghdr parent_msg;
size_t length;

/* Here the parent will accept the incoming requests and passed it to its children*/
for(;;)
{
    length = sizeof(client_address);
    if((accepted_socket_fd = accept(socket_fd, NULL, NULL)) < 0)
    {
        perror("accept()");
        exit(EXIT_FAILURE);
    }

    memset(&parent_msg, 0, sizeof(parent_msg));
    parent_msg.msg_name  = (char *) &accepted_socket_fd;
    parent_msg.msg_namelen = sizeof(accepted_socket_fd);

    if((sendmsg(server_sd, &parent_msg, 0)) < 0)
    {
        perror("sendmsg()");
        exit(EXIT_FAILURE);
    }

}

但不幸的是,我收到了这个错误:

But unfortunately, I got this error:

sendmsg(): Invalid argument

我应该怎么做才能解决这个问题?我是否正确使用了 msghdr 结构?因为在我上面提到的示例中,它们使用 msg_accrightsmsg_accrightslen 并且我在使用它们时遇到了一些错误,所以我不得不使用 msg_namemsg_namelen 代替.

What should I do to fix this problem? and am I using the msghdr structure correctly? because in the example I mentioned above, they use msg_accrights and msg_accrightslen and I got some error when I use them so I had to use msg_name and msg_namelen instead.

推荐答案

这很难做到.我建议只使用一个为你做这件事的库.最简单的方法之一是 libancillary.它为您提供了两个功能,一个是通过 UNIX 域套接字发送文件描述符,另一个是接收一个.它们使用起来非常简单.

This is extremely hard to get right. I'd recommend just using a library that does it for you. One of the simplest is libancillary. It gives you two functions, one to send a file descriptor over a UNIX-domain socket and one to receive one. They are absurdly simple to use.

这篇关于如何使用 sendmsg() 在 2 个进程之间通过套接字发送文件描述符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆