Правильное соединение клиент-сервер FIFO - PullRequest
7 голосов
/ 23 декабря 2011

Я пытаюсь написать простые клиентские и серверные программы на Си, взаимодействующие друг с другом в отдельных терминалах.

Сервер должен создать публичный fifo и ждать клиента.Тем временем клиент создает свой собственный fifo, через который приходит ответ сервера.Задача клиента - отправить серверу имя, созданное в очереди, и получить в ответ результат команды ls.

Я выполнил поиск ответа, например: fifo-server-программа , пример использования именованных каналов в linux-bash , как отправить простую строку между двумя программами используя-pipes .Я начал с кода из третьей ссылки и медленно его модифицировал.

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

РЕДАКТИРОВАТЬ: Я получил это работает!: D Коды приведены ниже, возможно, это кому-нибудь поможет.

Код 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;
}

Код 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;
}

Ответы [ 2 ]

5 голосов
/ 23 декабря 2011

Почему бы вам просто не управлять обоими fifo на сервере?Простое изменение кода для этого заставляет его работать правильно.

Если вы действительно хотите иметь отношения клиент-сервер, когда сервер обслуживает много разных клиентов, сокеты, вероятно, будут лучшим выбором.

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 голосов
/ 23 декабря 2011

Это работает только один раз из-за того, как работают именованные каналы.Каждый раз, когда вы open именованный канал для чтения, вы блокируете, пока другой процесс не откроет его для записи.Затем вы соединяетесь в пару, и файловый дескриптор связывает ваши процессы.Как только любой конец закроет это соединение, это конец этой трубы.Чтобы ваш сервер «принял другое соединение», он должен переместить open и close каналов в свой основной цикл, чтобы его можно было соединять снова и снова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...