您socketpair
只能在创建两个进程的地方使用,如下所示:
- call
socketpair
- 现在你有两个套接字文件描述符(单个管道的两端)
- 指定一端为父端,另一端为子端。无所谓,做个选择,以后坚持
- 呼叫
fork
- 现在您有两个进程
- 如果
fork
返回零,你就是孩子。关闭父文件描述符,保留子描述符,并将其用作该进程的管道末端
- 如果
fork
返回非零,则您是父级。关闭子文件描述符,保留父文件描述符并将其用作管道的末端
- 您现在有两个进程,每个进程都有一个文件描述符,代表同一管道的不同端。请注意,两个进程都在运行同一个程序,但在调用
fork
. 如果父级调用write
其套接字,则子级将能够从其套接字读取该数据,反之亦然
这是直接翻译成代码:
void child(int socket) {
const char hello[] = "hello parent, I am child";
write(socket, hello, sizeof(hello)); /* NB. this includes nul */
/* go forth and do childish things with this end of the pipe */
}
void parent(int socket) {
/* do parental things with this end, like reading the child's message */
char buf[1024];
int n = read(socket, buf, sizeof(buf));
printf("parent received '%.*s'\n", n, buf);
}
void socketfork() {
int fd[2];
static const int parentsocket = 0;
static const int childsocket = 1;
pid_t pid;
/* 1. call socketpair ... */
socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
/* 2. call fork ... */
pid = fork();
if (pid == 0) { /* 2.1 if fork returned zero, you are the child */
close(fd[parentsocket]); /* Close the parent file descriptor */
child(fd[childsocket]);
} else { /* 2.2 ... you are the parent */
close(fd[childsocket]); /* Close the child file descriptor */
parent(fd[parentsocket]);
}
exit(0); /* do everything in the parent and child functions */
}
请注意,这只是示例代码:我省略了所有错误检查和合理的流协议。
如果您希望两个单独的程序进行通信(例如,您有一个名为client的可执行文件,一个名为server的可执行文件),则不能使用此机制。相反,您可以:
- 使用 UNIX 套接字(其中一台主机上的 IPC 管道由文件名标识 - 仅当客户端和服务器在同一台机器上运行时才有效)
- 或使用 TCP/IP 套接字(IP 地址和端口标识管道,客户端和服务器可以在不同的机器上)
如果您并不特别需要套接字,并且很乐意要求客户端和服务器在同一台机器上运行,那么您也可以使用共享内存或消息队列。