2012-06-16 9 views
16

Estoy realmente interesado en la programación dirigida por eventos en C, especialmente con tomas de corriente, así que voy a dedicar algo de tiempo a hacer mis investigaciones.Modelo impulsado por eventos en C

Supongamos que quiero construir un programa con mucha E/S de archivos y redes como una aplicación cliente/servidor, básicamente la primera pregunta es cuál es la filosofía detrás de este modelo. Mientras que en la programación normal generaría nuevos procesos, ¿cómo es que un solo proceso puede realmente atender muchas otras solicitudes? Por ejemplo, hay algunos servidores web que pueden manejar conexiones sin crear hilos u otros procesos, solo un proceso principal.

Sé que esto es complicado, pero siempre es bueno saber cómo es la infraestructura de este tipo de programación.

+0

Si va a hacer algún tipo de conexión de linux, recomendaría la guía de Beejs aquí http://beej.us/guide/bgnet/ – mathematician1975

+0

Gracias por la recomendación, ¿este libro explica o contiene algún tipo de evento controlado referencia de programación? – iNDicator

+1

No está claro lo que está preguntando, pero podría comenzar leyendo, por ejemplo, la documentación de libevent. – Artefacto

Respuesta

17

Definitivamente debe leer lo siguiente: http://www.kegel.com/c10k.html. Esa página es la descripción perfecta de las técnicas controladas por eventos y asincrónicas.

Sin embargo, rápida & respuesta sucia: controlada por eventos no es ni bloqueante ni asincrónica.

Evento-impulsado significa que el proceso controlará sus descriptores de archivos (y sockets), y actuará solo cuando ocurra algún evento en algún descriptor (los eventos son: datos recibidos, error, escriturables, ...).

Los conectores BSD tienen la función "seleccionar()". Cuando se llame, el sistema operativo controlará los descriptores y regresará al proceso tan pronto como ocurra algún evento en uno de los descriptores.

Sin embargo, el sitio web anterior tiene descripciones mucho mejores (y detalles sobre las diferentes API).

+0

Gracias por el enlace, parece que esto es lo que estoy buscando;) – iNDicator

+0

@iNDicator: ¡deberías aceptar una respuesta! – Frunsi

+0

Esta respuesta es ** incorrecta **. "conducido por eventos" es por su naturaleza asincrónica. Nada monitorea nada. El evento en sí deriva las operaciones. Ver mi respuesta para más detalles. – Graham

0

En realidad, es muy específico de la plataforma en cuanto a cómo funciona.

si su funcionamiento en un sistema Linux en realidad no lo es a difícil, sin embargo, sólo hay que generar una copia de su proceso de uso de algo 'tenedor' como la siguiente haría el truco:

#include <sys/types.h> 
#include <sys/socket.h> 
#include <stdio.h> 
#include <netinet.h> 
#include <signal.h> 
#include <unistd.h> 

int main() 
{ 
    int server_sockfd, client_sockfd; 
    int server_len, client_len; 
    struct sockaddr_in server_address; 
    struct sockaddr_in client_address; 

    server_sockfd = socket(AF_INET, SOCK_STREAM, 0); 

    server_address.sin_family = AF_INET; 
    server_address.sin_addr.s_addr = htonl(INADDR_ANY); 
    server_Address.sin_port = htons(1234); 
    server_len = sizeof(server_address); 
    bind(server_sockfd, (struct sockaddr *)&server_address, server_len); 

    listen(server_sockfd, 5); 

    signal(SIGCHLD, SIG_IGN); 

    while(1) 
    { 
    char ch; 
    printf("Server Waiting\n"); 
    client_len = sizeof(client_address); 
    client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len) 

    // Here's where we do the forking, if you've forked already then this will be the child running, if not then your still the parent task. 

    if(fork() == 0) 
    { 
     // Do what ever the child needs to do with the connected client 
     read(client_sockfd, &ch, 1); 
     sleep(5); // just for show :-) 
     ch++; 
     write(client_sockfd, &ch, 1); 
     close(client_sockfd); 
     exit(0); 
    } 
    else 
    { 
     // Parent code here, close and loop for next connection 
     close(client_sockfd); 
    } 
    } 
} 

Usted puede Tengo que jugar con ese código un poco. No estoy cerca de una caja de Linux en este momento para hacer una compilación de prueba, y la he tipeado de memoria.

Sin embargo, el uso de la horquilla es la forma estándar de hacerlo en C en un sistema basado en Linux/Unix.

En windows es una historia muy diferente, y una que no puedo recordar todo el código necesario (estoy acostumbrado a la codificación en C# en estos días) pero configurar el socket es prácticamente el mismo, excepto necesita usar la API 'Winsock' para una mejor compatibilidad.

Usted puede (creo que de todos modos) todavía utilizar sockets Berkley estándar en Windows pero está lleno de trampas y agujeros, para las ventanas del Winsock este es un buen lugar para empezar:

http://tangentsoft.net/wskfaq/

Por lo que yo También soy consciente de que si usas Winsock tiene cosas para ayudar con el desove y el cliente múltiple, yo personalmente, por lo general, solo hago girar un hilo separado y copio la conexión del socket a eso, luego vuelvo al lazo escuchando mi servidor

+1

Muchas gracias por su ejemplo, sin embargo, aquí no se crea el nuevo proceso hijo?entonces, si tuviéramos 30 clientes conectados, ¿no obtendríamos 30 nuevos procesos? – iNDicator

+1

De hecho, sí crea procesos secundarios, pero no hay procesos completos, hay tareas parciales derivadas de los padres que solo duran la vida útil del servicio. La otra forma en que podría hacerlo, es usar PThreads de Linux que aún genera un subproceso, pero no en su propio grupo de memoria como hace Fork. La gran mayoría de los servicios de Linux usan la forma de hacer las cosas de Fork. – shawty

+0

Bueno, esto es lo que quiero evitar, vea la publicación de Frunsi. ¡este parece ser lo que necesito! no que el suyo no sea útil;) – iNDicator

1

La programación basada en eventos se basa en un bucle de eventos.El ciclo simplemente espera un nuevo evento, envía un código para manejar el evento y luego regresa para esperar el próximo evento. En el caso de los sockets, está hablando de "programación de red asíncrona". Esto implica select() o alguna otra opción como Kqueue() para esperar los eventos en el ciclo de evento. Los sockets deberían establecerse en sin bloqueo, de modo que cuando lea() o escriba() su código no espere a que se complete la E/S.

La programación de red asíncrona puede ser muy compleja y complicada de hacer bien. Vea un par de presentaciones here y here. Recomiendo utilizar una biblioteca como libevent o liboop para hacerlo bien.

+0

gracias por los enlaces – iNDicator

1

Ese tipo de servidores/clientes TCP se pueden implementar utilizando select(2) tomas de llamada y no de bloqueo.

Es más complicado utilizar tomas no bloqueantes que enchufes.

Ejemplo:

connect llamada generalmente regreso -1 inmediatamente y establece errno EINPROGRESS cuando se utilizan de no bloqueo socket. En este caso, debe usar select para esperar cuando se abre o falla la conexión. connect también puede devolver 0. Esto puede suceder si crea una conexión con el host local. De esta manera puede atender otros sockets, mientras que un socket abre una conexión TCP.

2

"¿Qué es la filosofía detrás de este modelo"

medios controlados por eventos que no hay "seguimiento", pero que el evento en sí inicia la acción.

Normalmente esto se inicia mediante una interrupción, que es una señal para el sistema desde un dispositivo externo, o (en el caso de una interrupción de software) un proceso asíncrono.

https://en.wikipedia.org/wiki/Interrupt

Otras lecturas parece ser aquí:

https://docs.oracle.com/cd/E19455-01/806-1017/6jab5di2m/index.html#sockets-40 - "Zócalo de E/S dirigida por interrupciones"

también http://cs.baylor.edu/~donahoo/practical/CSockets/textcode.html tiene algunos ejemplos de sockets controlada por alarmas, así como otros ejemplos de programación de socket.

Cuestiones relacionadas