加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

如何使用sendmsg()通过两个进程之间的套接字发送文件描述符?

发布时间:2020-12-13 19:12:06 所属栏目:Linux 来源:网络整理
导读:在@cnicutar在这个question上回答我之后,我试图从父进程向其子??进程发送一个文件描述符.基于这个example,我写了这段代码: int socket_fd,accepted_socket_fd,on = 1;int server_sd,worker_sd,pair_sd[2];struct sockaddr_in client_address;struct sockadd

在@cnicutar在这个question上回答我之后,我试图从父进程向其子??进程发送一个文件描述符.基于这个example,我写了这段代码:

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,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,sizeof(child_msg));
            memset(iov,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 recvmsgn");
            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 receivedn");
               close(worker_sd);
               exit(-1);
            }
            else
            {
               printf("Received descriptor = %dn",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,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);
    }

}

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

sendmsg(): Invalid argument

我该怎么做才能解决这个问题?我正确使用msghdr结构吗?因为在我上面提到的例子中,他们使用msg_accrights和msg_accrightslen,当我使用它时出现了一些错误,所以我不得不使用msg_name和msg_namelen.

最佳答案
这很难做到.我建议你只使用一个为你做这个的库.其中最简单的是libancillary.它为您提供了两个函数,一个用于通过UNIX域套接字发送文件描述符,另一个用于接收一个.它们使用起来很荒谬.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读