Correct client-server FIFO connection

I am trying to write simple C client and server programs by exchanging with each other in separate terminals.

The server needs to create a public fifo and wait for the client. Meanwhile, the client creates its own fifo, through which the server will respond. The client task sends the server the name created in the queue and returns the result of the ls .

I searched for the answer, for example: fifo-server-program , example-of-using-named-pipes-in-linux-bash , how-to-send-a-simple-string-between-two-programs-using-pipes . I started with the code from the third channel and slowly changed it.

Now I have a client that accepts input from the user, sends it to the server and receives it back. But it works only once. I have no idea why. The body of the main function is below. I will be grateful for any help.

EDIT: I will earn !: D Cheats below, maybe this will help someone.

Server.c code:

 #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 Code:

 #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; } 
+6
source share
2 answers

Why do not you just manage both of the names on the server? Just changing the code for this makes it work correctly.

If you really want to have a client-server relationship with a server serving many different clients, sockets are probably the best choice.

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; } 
+5
source

It only works once because of the way named pipes work. Each time you open named pipe for reading, you block until another process opens it for writing. Then you connect and the file descriptor connects your processes. As soon as the end completes this connection, the end of this channel. In order for your server to "accept another connection", it needs to move the open and close tags into its main loop so that it can connect again and again.

+4
source

Source: https://habr.com/ru/post/904356/


All Articles