2011-12-23 46 views
6

Estoy intentando escribir programas C de cliente y servidor simples, comunicándome en terminales separados.Conexión de cliente-servidor FIFO adecuada

El servidor tiene que crear un fifo público y esperar al cliente. Mientras tanto, el cliente está creando su propia fifo a través de la cual vendrá la respuesta del servidor. La tarea del cliente es enviar al servidor un nombre creado por la cola y obtener a cambio el resultado del comando ls.

He buscado una respuesta, por ejemplo: fifo-server-program, example-of-using-named-pipes-in-linux-bash, how-to-send-a-simple-string-between-two-programs-using-pipes. Empecé con el código del tercer enlace y lo modifiqué lentamente.

Lo que tengo ahora, es un cliente que recibe la información del usuario, la envía al servidor y la vuelve a recibir. Pero solo funciona una vez. No tengo ni idea de porqué. El cuerpo de la función principal está debajo. Estaré agradecido por cualquier ayuda.

EDITAR: I got it working! : D Los códigos están a continuación, tal vez ayudará a alguien.

El código server.c:

#include <unistd.h> 
#include <stdio.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <string.h> 

int main(int argc, char* argv[]) 
{ 
    int fds[2]; 
    char tab[BUFSIZ]; 
    int fd, n; 

    char *myfifo = "/tmp/serwer"; 
    char *myfifo2 = "/tmp/client"; 

    pipe(fds); 
    mkfifo(myfifo,0666); 

    while(1) 
    { 
     fds[0]=open(myfifo2,O_RDONLY); 
     fds[1]=open(myfifo,O_WRONLY); 

     read(fds[0],tab,BUFSIZ); 

     if (strcmp("klient",tab)==0) { 
      printf("Od klienta: %s\n",tab); 
      fd=open(tab,O_WRONLY); 

      if(fork()==0) 
      { 
       dup2(fds[1],1); 
       close(fds[1]); 
       execlp("ls","ls","-l",NULL); 
       close(fds[0]); 
       close(fds[1]); 
      } 
      else 
      { 
       dup2(fds[0],0); 
       n = read(fds[0],tab,BUFSIZ); 
       write(fd,tab,n); 
       close(fds[0]); 
       close(fds[1]); 
      } 
     } 
     memset(tab, 0, sizeof(tab)); 
     close(fd); 
     close(fds[0]); 
     close(fds[1]); 
    } 

    unlink(myfifo); 
    return 0; 
} 

El código client.c:

#include <unistd.h> 
#include <stdio.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <string.h> 

int main(int argc, char* argv[]) 
{ 
    int fds[2]; 
    char *myfifo = "/tmp/serwer"; 
    char *myfifo2 = "/tmp/client"; 

    mkfifo(myfifo2,0666); 
    fds[0]=open(myfifo,O_RDONLY); 
    fds[1]=open(myfifo2,O_WRONLY); 

    char tab[BUFSIZ]; 
    memset(tab, 0, sizeof(tab)); 

    write(fds[1],"klient",6); 
    perror("Write:"); //Very crude error check 
    read(fds[0],tab,sizeof(tab)); 
    perror("Read:"); // Very crude error check 

    printf("Odebrano od serwera: %s\n",tab); 

    close(fds[0]); 
    close(fds[1]); 
    unlink(myfifo2); 
    return 0; 
} 
+1

No se desprende de este código. ¿Has conseguido la salida de ls o estás enviando mensajes pequeños? La trampa habitual en este escenario es que el punto muerto es que el servidor está esperando la entrada mientras el cliente está esperando la entrada. Esperan por siempre porque nadie está enviando nada. – Duck

+0

No, el comando ls no está funcionando aún. Estos programas funcionan una vez: el servidor espera un mensaje, lo devuelve al cliente y el cliente puede cerrarlo. Cuando deseo enviar otro mensaje, tanto el cliente como el servidor dejan de responder. – uluroki

Respuesta

5

¿Por qué no acaba de gestionar ambos FIFO en el servidor? Simplemente cambiando su código para hacer esto hace que funcione correctamente.

Si realmente desea tener una relación cliente-servidor, con un servidor que atienda a muchos clientes diferentes, los enchufes probablemente sean una mejor opción.

client.cpp

#include <stdio.h> 
#include <fcntl.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <unistd.h> 

int main() 
{ 
    int client_to_server; 
    char *myfifo = "/tmp/client_to_server_fifo"; 

    int server_to_client; 
    char *myfifo2 = "/tmp/server_to_client_fifo"; 

    char str[BUFSIZ]; 
    printf("Input message to serwer: "); 
    scanf("%s", str); 


    /* write str to the FIFO */ 
    client_to_server = open(myfifo, O_WRONLY); 
    server_to_client = open(myfifo2, O_RDONLY); 
    write(client_to_server, str, sizeof(str)); 

    perror("Write:"); //Very crude error check 

    read(server_to_client,str,sizeof(str)); 

    perror("Read:"); // Very crude error check 

    printf("...received from the server: %s\n",str); 
    close(client_to_server); 
    close(server_to_client); 

    /* remove the FIFO */ 

    return 0; 
} 

server.cpp

#include <fcntl.h> 
#include <stdio.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <string.h> 

int main() 
{ 
    int client_to_server; 
    char *myfifo = "/tmp/client_to_server_fifo"; 

    int server_to_client; 
    char *myfifo2 = "/tmp/server_to_client_fifo"; 

    char buf[BUFSIZ]; 

    /* create the FIFO (named pipe) */ 
    mkfifo(myfifo, 0666); 
    mkfifo(myfifo2, 0666); 

    /* open, read, and display the message from the FIFO */ 
    client_to_server = open(myfifo, O_RDONLY); 
    server_to_client = open(myfifo2, O_WRONLY); 

    printf("Server ON.\n"); 

    while (1) 
    { 
     read(client_to_server, buf, BUFSIZ); 

     if (strcmp("exit",buf)==0) 
     { 
     printf("Server OFF.\n"); 
     break; 
     } 

     else if (strcmp("",buf)!=0) 
     { 
     printf("Received: %s\n", buf); 
     printf("Sending back...\n"); 
     write(server_to_client,buf,BUFSIZ); 
     } 

     /* clean buf from any data */ 
     memset(buf, 0, sizeof(buf)); 
    } 

    close(client_to_server); 
    close(server_to_client); 

    unlink(myfifo); 
    unlink(myfifo2); 
    return 0; 
} 
4

Sólo funciona una vez debido a cómo funcionan las canalizaciones con nombre. Cada vez que open un tubo con nombre para lectura lo bloquea hasta que otro proceso lo abra para escritura. Entonces estás emparejado y el descriptor de archivo conecta tus procesos. Una vez que cualquiera de los extremos cierra esa conexión, ese es el final de esa tubería. Para que su servidor "acepte otra conexión" necesita mover el open y el close de las tuberías en su bucle principal para que pueda emparejarse una y otra vez.