如何使用SENDMSG()通过套接字送2进程之间文件描述符? [英] How to use sendmsg() to send a file-descriptor via sockets between 2 processes?
问题描述
在@cnicutar回答我这个<一个href=\"http://stackoverflow.com/questions/8457402/why-we-cannot-accept-a-socket-on-some-process-and-recv-data-from-its-child\">question,我试图从父进程发送一个文件描述符到其子。在此基础上<一href=\"http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=/rzab6/xdescriptors.htm\">example,我写这篇code:
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\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);
}
}
但不幸的是,我得到这个错误:
But unfortunately, I got this error:
sendmsg(): Invalid argument
我应该怎么做才能解决这个问题?和我使用正确指向msghdr
结构?因为在例子中,我上面提到的,它们使用 msg_accrights
和 msg_accrightslen
,我得到了一些错误,当我使用它们,所以我不得不使用 msg_name
和 msg_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屋!