当前位置: 首页 > 面试题库 >

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

夏侯弘量
2023-03-14
问题内容

@cnicutar在此问题上回答了我之后,我尝试将文件描述符从父进程发送到其子进程。基于此示例,我编写了以下代码:

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\n");
            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\n");
               close(worker_sd);
               exit(-1);
            }
            else
            {
               printf("Received descriptor = %d\n", 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);
    }

}

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

sendmsg(): Invalid argument

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


问题答案:

这是很难做到的。我建议仅使用为您提供帮助的图书馆。最简单的一种是libancillary。它提供了两种功能,一种是通过UNIX域套接字发送文件描述符,另一种是接收文件描述符。它们使用起来非常荒谬。



 类似资料:
  • 问题内容: 我正在尝试通过linux套接字发送一些文件描述符,但是它不起作用。我究竟做错了什么?应该如何调试这样的东西?我尝试将perror()放到所有可能的地方,但是他们声称一切正常。这是我写的: 问题答案: 史蒂文斯(etal)[UNIX®网络编程,第1卷:套接字网络API描述了在第15章 Unix域协议 (尤其是第15.7节:_传递描述_符)中的过程之间传输文件描述符的过程。对此进行完整描述

  • 问题内容: 您好,我尝试使用Java中的客户端-服务器类发送文件。由于某种原因,当调用发送文件的方法时,套接字关闭。这是代码: 和来自客户端的代码: 和我得到的错误消息:严重:null java.net.SocketException:套接字已关闭 我对此并没有真正的经验,所以如果有帮助的话会很棒。 问题答案: 该方法返回一个,代表它实际读取的字节数。不能保证从字节数组中读取所需的字节数。它通常会

  • 问题内容: 我正在尝试用Python编写一个实现套接字的程序,每个客户端发送一个PDF文件,服务器接收该文件,标题更改为“ file_number.pdf”(即:file_1.pdf)。出现的问题是只有客户端才能成功发送文件。当第二个客户端尝试发送程序时,它确实崩溃了。我在做什么错,我该如何解决我的代码以允许N个客户端(N <20)连接到服务器并传输文件? 这是服务器代码: 这是客户端代码: 为了

  • 我必须对FTP服务器进行编码,而且我在数据传输方面遇到了问题。 我在linux上使用ftp命令来测试它,我目前正在使用,它发送工作目录中的文件/目录列表。一切正常(ftp打印文件列表),除了ftp打印以下警告: 我想删除该警告,我认为ftp需要二进制数据,但我不知道如何通过套接字发送这样的数据,我目前正在使用最基本的方式发送结果:

  • 问题内容: 我使用这里的代码通过套接字发送单个文件。但是,我需要能够通过套接字发送多个文件(基本上是目录中的所有文件),并使客户端识别文件之间的分隔方式。坦白说,我完全不知所措。任何提示都会有所帮助。 注意1: 我需要一种以连续流方式发送文件的方法,客户端可以将其分离成单独的文件。它不能依赖客户端的个别请求。 注意2: 我很肯定会回答一个问题,不,这 不是 家庭作业。 编辑 建议我可以在文件本身之

  • 问题内容: 我正在尝试开发一个非常简单的客户端/服务器,其中客户端将文件转换为字节,将其发送到服务器,然后将字节转换回文件。 当前,程序仅创建一个空文件。我不是一个出色的Java开发人员,因此不胜感激。 这是接收客户端发送的内容的服务器部分。 这是客户端部分 问题答案: 在Java中复制流的正确方法如下: 希望我每次在论坛上发布时都能获得一美元。