Par de sockets() en C/Unix

8 minutos de lectura

avatar de usuario
Pasante de la NASA

Tengo 2 aplicaciones en el mismo sistema que necesito comunicar de un lado a otro. Según mi investigación, creo que esto se llama Comunicación entre procesos y el uso de socketpair () es el mejor método para mi problema.

Me estoy arrancando los pelos (literalmente) tratando de comenzar a crear sockets con socketpair() en C. Por lo que entiendo, los sockets son un tema muy complejo y ser un programador novato de C seguramente no está ayudando a la situación.

Busqué en Google durante las últimas 48 horas, leí tutoriales, etc., pero todavía no puedo obtenerlo. Entiendo el concepto, pero el código es demasiado confuso. He leído este artículo varias veces: http://beej.us/guide/bgnet/html/single/bgnet.htmlpero no es lo suficientemente simple.

¿Puede alguien dar algún ejemplo (tan simple que un estudiante de 5to grado podría entender) o indicarme un buen tutorial?

  • Por favor, no te arranques literalmente el pelo. Eso suena doloroso. La primera pregunta que debemos responder es esta: ¿los dos programas están conectados por un ancestro común? Es decir, ¿uno lanza al otro? ¿O son lanzados por un tercer programa que ha escrito? ¿O se lanzan independientemente uno del otro?

    – Robᵩ

    12 de julio de 2012 a las 21:42

  • Amigo, IPC no se trata de enchufes. es una cosa totalmente diferente. en lugar de seguir el enlace que ha publicado, debe seguir este …..beej.us/guide/bgipc/output/html/multipage/…

    – Afnix

    12 de julio de 2012 a las 21:44

  • Los 2 programas están conectados por un ancestro común.

    – Pasante de la NASA

    12 de julio de 2012 a las 22:34

  • Ese ejemplo es genial! ¡justo lo que estaba buscando!

    – Pasante de la NASA

    17 de julio de 2012 a las 0:28

  • @Aftnix Supongo que estabas buscando ese complemento alimenticio de “bondad” el otro día. El mismo artículo al que se vincula tiene este sabroso bocado en el tercer párrafo: “puede usar inmediatamente estos descriptores de socket para la comunicación entre procesos”. Eso deletrea IPC en mi libro de siglas. ¡Y oye, mira el nombre de usuario del “amigo”! A menos que esté bromeando, en realidad podría ser un científico espacial, que merece un poco más de respeto (en mi humilde opinión, FWIW).

    – ack

    18 de febrero de 2015 a las 15:04


avatar de usuario
Inútil

Puedes usar socketpair solo donde creas ambos procesos, así:

  1. llamada socketpair – ahora tiene dos descriptores de archivo de socket (dos extremos de una sola tubería)
    • nominar un extremo para ser el padre y uno para ser el niño final. No importa cuál, solo toma una decisión y apégate a ella más tarde.
  2. llamada fork – ahora tienes dos procesos
    1. si fork devolvió cero, usted es el niño. Cierra el padre descriptor de archivo, mantenga el niño descriptor, y utilícelo como el final de la tubería de este proceso
    2. si fork devuelto distinto de cero, usted es el padre. Cierra el niño descriptor de archivo, mantenga el padre uno y utilícelo como su extremo de la tubería
  3. ahora tiene dos procesos, cada uno tiene un descriptor de archivo que representa diferentes extremos de la misma tubería. Tenga en cuenta que ambos procesos ejecutan el mismo programa, pero siguieron una rama diferente después de llamar fork. Si padre llamadas write en su zócalo, niño será capaz de leer esos datos de su enchufe, y viceversa

Aquí hay una traducción directa al código:

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 */
}

Tenga en cuenta que esto es solo un código de muestra: he omitido todas las comprobaciones de errores y un protocolo de transmisión sensato.


si quieres dos separar programas para comunicarse (por ejemplo, tiene un ejecutable llamado clientey uno llamado servidor), no puede utilizar este mecanismo. En cambio, podrías:

  • use sockets UNIX (donde una tubería IPC en un host se identifica mediante un nombre de archivo; esto solo funciona si cliente y servidor ejecutar en la misma máquina)
  • o use sockets TCP/IP (donde una dirección IP y un puerto identifican la tubería y el cliente y servidor puede estar en diferentes máquinas)

si no lo haces específicamente necesita enchufes, y está feliz de requerir eso cliente y servidor ejecutarse en la misma máquina, también puede usar memoria compartida o colas de mensajes.

  • Pueden ser programas separados con un ancestro común. Solo usa execl (u otra llamada ejecutiva) para ejecutar el programa y heredará el socket. Solo necesita una forma de decirle al programa que use el socket que heredó.

    – marca4o

    13 de julio de 2012 a las 3:01

  • cierto, pero para cuando tenga ese protocolo, obviamente no es mucho más fácil que simplemente usar sockets UNIX

    – Inútil

    13 de julio de 2012 a las 9:36

  • En realidad, puede pasar un descriptor a un proceso no relacionado: vea sendmsg/recvmsg y “paso de descriptor”. Parece ser una búsqueda popular 🙂

    – tenedor0

    13 de julio de 2012 a las 13:15


  • ciertamente: todavía son solo dos extremos de una tubería, y no hay nada especial en un proceso secundario u otro.

    – Inútil

    3 de diciembre de 2015 a las 10:16

  • ¿Por qué cierra el otro extremo del zócalo en los procesos padre e hijo? ¿Es eso necesario? ¿Y se puede usar socketpair para comunicarse entre dos subprocesos del mismo proceso?

    – Guillaume Brunerie

    20 de enero de 2017 a las 23:05

socketpair crea un anónimo par de sockets, generalmente sockets unix/locales, que solo son útiles para la comunicación entre un proceso principal y un proceso secundario o en otros casos donde los procesos que necesitan usarlos pueden heredar los descriptores de archivo de un ancestro común.

Si va a comunicarse entre procesos no relacionados (en el sentido de paternidad), debe usar socket, bindy connect para crear un socket de escucha en un proceso y crear un socket de cliente para conectarse a él en el otro proceso.

  • curiosamente, encuentro código de ejemplo de par de sockets con una simple búsqueda de esa frase. He proporcionado algunos, pero me sorprende que sea necesario.

    – Inútil

    13 de julio de 2012 a las 9:38

  • @Useless: Esa búsqueda suena bastante inútil ya que estaba señalando que socketpair probablemente no sea la herramienta adecuada para lo que OP quiere hacer.

    – R.. GitHub DEJA DE AYUDAR A ICE

    13 de julio de 2012 a las 14:31

Para la comunicación entre dos procesos, sí, Inter Process Communication o IPC es lo que debe buscar. Los sockets son solo uno de los métodos para comunicarse y son útiles si tiene que implementar una conexión de uno a muchos. Significa, un proceso de servidor que se comunica con muchos procesos de cliente en forma de solicitud-respuesta. Como usted es un novato en IPC, es comprensible que las direcciones de socket y los detalles involucrados puedan parecer difíciles de comprender. (Aunque los encontrará fáciles a su debido tiempo :-))

Para su problema, le sugiero que use mecanismos IPC más simples como Pipe, FIFO, Message Queue. No estoy seguro de cómo llegaste a la conclusión de usar socketpair. Dado que no ha mencionado nada sobre el diseño o el tipo de IPC que necesita Y, según el nivel de uso, le recomiendo que consulte los códigos de muestra de Pipe o FIFO en algún libro o en Internet. Deberían verse mucho más fáciles de implementar y funcionar más rápido que los sockets.

  • ¿Qué quiere decir con FIFO (la publicación sugiere que es diferente a Pipe)?

    – cúpula

    16 sep 2019 a las 14:35

Utilice TCP/IP. Si bien hay otros mecanismos IPC disponibles (como sockets de dominio Unix y SYSV IPC), es mejor usar TCP/IP por muchas razones. Aquí están algunas:

  1. Hay muchos tutoriales y otra información en la web que describen cómo hacer TCP/IP.
  2. Los sistemas modernos, y especialmente Linux y *BSD, no imponen una penalización significativa por usar TCP/IP en comparación con, por ejemplo, los sockets de dominio de Unix o incluso SYSV IPC.
  3. Hay una serie de bibliotecas y marcos que puede utilizar para las aplicaciones que se comunican a través de TCP/IP.

El único caso en el que no usaría TCP/IP para comunicarse entre dos “programas” es en el caso de que realmente sean subprocesos en lugar de programas separados.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad