Подтвердить что ты не робот

Socketpair() в C/Unix

У меня есть 2 приложения в той же системе, что мне нужно общаться туда и обратно. Из моих исследований я считаю, что это называется Inter Process Communication, и использование socketpair() - лучший метод для моей проблемы.

Я разрываю волосы (буквально), пытаясь начать создавать сокеты с socketpair() на C. Из того, что я понимаю, сокеты - очень сложная тема, и я, будучи программистом-новичком, несомненно, не помогает ситуации.

Я искал Google за последние 48 часов, читал учебники и т.д., Но я до сих пор не могу это получить. Я понимаю концепцию, но код слишком запутан. Я читал эту статью несколько раз: http://beej.us/guide/bgnet/html/single/bgnet.html, но это не достаточно просто.

Может ли кто-нибудь предоставить какой-то пример (так легко понять пятый классник) или указать мне хороший учебник?

4b9b3361

Ответ 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-адрес и порт идентифицируют канал, а клиент и сервер могут находиться на разных компьютерах).

Если вам не нужны сокеты, и вы с удовольствием требуете, чтобы клиент и сервер выполнялись на одном компьютере, вы также можете использовать разделяемую память или очереди сообщений.

Ответ 2

socketpair создает анонимную пару сокетов, обычно это unix/local сокеты, которые полезны только для связи между родительским и дочерним процессом или в других случаях, когда процессы, которые должны их использовать, могут наследовать дескрипторы файлов из общий предок.

Если вы собираетесь осуществлять связь между несвязанными (в смысле происхождения) процессами, вам нужно использовать socket, bind и connect для создания прослушивающего сокета в одном процессе и создания клиента socket для подключения к нему в другом процессе.

Ответ 3

Для обмена данными между двумя процессами, да, Inter Process Communication или IPC - это то, что вы должны искать. Сокеты - это всего лишь один из способов общения и полезен, если вам нужно реализовать соединение "один ко многим". Средство, один серверный процесс, который взаимодействует со многими клиентскими процессами в режиме запроса-ответа. Поскольку вы новичок в IPC, понятно, что адреса сокетов и связанные с ними детали могут оказаться трудными для понимания. (Хотя вы найдете их в свое время легко: -))

Для вашей проблемы я предлагаю вам использовать более простые механизмы IPC, такие как Pipe, FIFO, Message Queue. Я не уверен, как вы пришли к выводу, что используете socketpair. Поскольку вы ничего не упомянули о дизайне или виде IPC, который вам нужен, и басировали на уровне использования, я настоятельно рекомендую посмотреть коды образцов Pipe или FIFO в некоторых книгах или Интернете. Они должны выглядеть проще для реализации и работы быстрее, чем сокеты.

Ответ 4

Использовать TCP/IP. Несмотря на наличие других доступных механизмов МПК (таких как сокеты домена Unix и SYSV IPC), вы по-прежнему лучше используете TCP/IP по многим причинам. Вот некоторые из них:

  • В Интернете есть много руководств и другой информации о том, как выполнять TCP/IP.
  • Современные системы, особенно Linux и * BSD, не налагают существенных штрафных санкций за использование TCP/IP по сравнению с, скажем, сокетами Unix или даже SYSV IPC.
  • Существует несколько библиотек и фреймворков, которые вы можете использовать для приложений, обменивающихся по TCP/IP.

Единственный случай, когда я не буду использовать TCP/IP для связи между двумя "программами", - это случай, когда они являются действительно потоками, а не отдельными программами.