Ответ 1
Вы можете использовать socketpair
только там, где вы создаете оба процесса, например:
- call
socketpair
- теперь у вас есть два дескриптора файла сокета (два конца одного канала)- назначьте один конец родителем, а другой - дочерним. Неважно, что, просто сделайте выбор и придерживайтесь его позже.
- call
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 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 */
}
Обратите внимание, что это всего лишь образец кода: я оставил всю проверку ошибок и разумный протокол потока.
Если вы хотите, чтобы две отдельные программы связывались (например, у вас есть исполняемый клиент, и один вызываемый сервер), вы не можете использовать этот механизм. Вместо этого вы можете:
- использовать UNIX-сокеты (где IPC-канал на одном хосте идентифицируется по имени файла - это работает только в том случае, если клиент и сервер работают на одном компьютере)
- или использовать сокеты TCP/IP (где IP-адрес и порт идентифицируют канал, а клиент и сервер могут находиться на разных компьютерах).
Если вам не нужны сокеты, и вы с удовольствием требуете, чтобы клиент и сервер выполнялись на одном компьютере, вы также можете использовать разделяемую память или очереди сообщений.