用c/c++代码举例说明如何使用socket在进程间传递文件句柄
时间: 2023-06-19 11:10:20 浏览: 243
在 Unix/Linux 系统下,我们可以使用 `sendmsg` 和 `recvmsg` 函数来传递文件句柄。下面是一个简单的示例代码:
#### 发送进程代码
```c
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#define CONTROLLEN CMSG_LEN(sizeof(int))
int send_fd(int fd, int fd_to_send)
{
struct iovec iov[1];
struct msghdr msg;
char buf[2]; // 发送任意数据
int ret;
union {
struct cmsghdr cm;
char control[CONTROLLEN];
} control_un;
struct cmsghdr *pcmsg;
iov[0].iov_base = buf;
iov[0].iov_len = 2;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
if (fd_to_send >= 0) {
msg.msg_control = control_un.control;
msg.msg_controllen = CONTROLLEN;
pcmsg = CMSG_FIRSTHDR(&msg);
pcmsg->cmsg_len = CONTROLLEN;
pcmsg->cmsg_level = SOL_SOCKET;
pcmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(pcmsg) = fd_to_send;
} else {
msg.msg_control = NULL;
msg.msg_controllen = 0;
buf[1] = 0;
}
buf[0] = 0;
if ((ret = sendmsg(fd, &msg, 0)) < 0) {
perror("sendmsg");
}
return ret;
}
```
#### 接收进程代码
```c
int recv_fd(int fd)
{
struct iovec iov[1];
struct msghdr msg;
char buf[2];
int ret;
union {
struct cmsghdr cm;
char control[CONTROLLEN];
} control_un;
struct cmsghdr *pcmsg;
iov[0].iov_base = buf;
iov[0].iov_len = 2;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = control_un.control;
msg.msg_controllen = CONTROLLEN;
if ((ret = recvmsg(fd, &msg, 0)) < 0) {
perror("recvmsg");
return -1;
}
if (buf[0] != 0) {
printf("error: received %d bytes\n", ret);
return -1;
}
if ((pcmsg = CMSG_FIRSTHDR(&msg)) != NULL &&
pcmsg->cmsg_len == CONTROLLEN) {
if (pcmsg->cmsg_level != SOL_SOCKET) {
printf("error: control level != SOL_SOCKET\n");
return -1;
}
if (pcmsg->cmsg_type != SCM_RIGHTS) {
printf("error: control type != SCM_RIGHTS\n");
return -1;
}
return *(int *)CMSG_DATA(pcmsg);
} else {
return -1;
}
}
```
使用示例:
```c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int fd[2];
int ret;
char buf[256];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) {
perror("socketpair");
exit(1);
}
int send_fd = open("file.txt", O_RDONLY);
if (send_fd < 0) {
perror("open");
exit(1);
}
if ((ret = fork()) < 0) {
perror("fork");
exit(1);
}
if (ret == 0) { // 子进程
close(fd[0]);
int recv_fd = recv_fd(fd[1]);
if (recv_fd < 0) {
exit(1);
}
printf("received fd: %d\n", recv_fd);
read(recv_fd, buf, 256);
printf("read: %s\n", buf);
close(recv_fd);
exit(0);
} else { // 父进程
close(fd[1]);
send_fd(fd[0], send_fd);
close(send_fd);
waitpid(ret, NULL, 0);
exit(0);
}
}
```
在这个示例中,父进程打开了 `file.txt` 文件,并将其文件描述符通过 `send_fd` 函数发送给了子进程。子进程通过 `recv_fd` 函数接收到了文件描述符,并读取了文件中的内容。注意,这个示例中并没有考虑错误处理,实际应用中需要根据实际情况进行完善。
阅读全文