C语言 正确的 FIFO 客户端-服务器连接



我正在尝试编写简单的客户端和服务器C程序,在单独的终端中相互通信。

服务器必须创建一个公共 fifo 并等待客户端。同时,客户端正在创建自己的FIFO,服务器的响应将通过该FIFO进行。客户端的任务是向服务器发送队列创建的名称,并返回ls命令的结果。

我确实搜索了一个答案,例如:fifo-server-program,example-of-named-pipes-in-linux-bash,how-send-a-simple-string-between-two-programs-using-pipes。我从第三个链接的代码开始,慢慢修改它。

我现在得到的是一个客户端从用户那里获取输入,将其发送到服务器并接收回来。但它只有效一次。我不知道为什么。主要函数的主体如下。我将不胜感激任何帮助。

编辑:我让它工作了!:D代码在下面,也许它会帮助某人。

服务器代码:

#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: %sn",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;
}

客户端代码:

#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: %sn",tab);
    close(fds[0]);
    close(fds[1]);
    unlink(myfifo2);
    return 0;
}

为什么不在服务器中管理两个FIFO?只需更改代码即可使其正常工作。

如果您确实想要建立客户端-服务器关系,并且服务器为许多不同的客户端提供服务,则套接字可能是更好的选择。

客户端.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: %sn",str);
   close(client_to_server);
   close(server_to_client);
   /* remove the FIFO */
   return 0;
}

服务器.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: %sn", 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;
}

由于命名管道的工作方式,它只工作一次。 每次open命名管道进行读取时,都会阻止,直到另一个进程打开它进行写入。 然后,您将配对,文件描述符将连接您的进程。 一旦任一端关闭该连接,那就是该管道的末端。 为了让您的服务器"接受另一个连接",它需要将管道的openclose移动到其主回路中,以便可以一遍又一遍地配对。

相关内容

最新更新